需要c#游戏代码方面的帮助吗

需要c#游戏代码方面的帮助吗,c#,unity3d,C#,Unity3d,我正在unity做一个塔防游戏,但我被卡住了。我想让我的枪或炮塔面对敌人,直到他们超出射程,但每0.5秒,它就会更新并面对其射程内的另一个敌人,尽管第一个敌人也在射程内 这是我的密码: void Start () { InvokeRepeating("UpdateTarget", 0f , 0.5f ); } void UpdateTarget() { GameObject[] enemies = GameObject.FindGameObjectsWithTag(en

我正在unity做一个塔防游戏,但我被卡住了。我想让我的枪或炮塔面对敌人,直到他们超出射程,但每0.5秒,它就会更新并面对其射程内的另一个敌人,尽管第一个敌人也在射程内

这是我的密码:

void Start () 
{
    InvokeRepeating("UpdateTarget", 0f , 0.5f );
}   

void UpdateTarget()
{
    GameObject[] enemies = GameObject.FindGameObjectsWithTag(enemyTag);
    float shortestDistance = Mathf.Infinity;
    GameObject nearestEnemy = null;

    foreach (GameObject enemy in enemies)
    {
        float distanceToEnemy = Vector3.Distance(transform.position, enemy.transform.position);
        if (distanceToEnemy < shortestDistance)
        {
            shortestDistance = distanceToEnemy;
            nearestEnemy = enemy;
        }
    }

    if (nearestEnemy != null && shortestDistance <= range)
    {
        target = nearestEnemy.transform;          
    }
    else 
    { 
        target = null; 
    }        
}
void Start()
{
调用重复(“UpdateTarget”,0f,0.5f);
}   
void UpdateTarget()
{
GameObject[]敌人=GameObject.FindGameObjectsWithTag(enemyTag);
浮点最短距离=数学无穷大;
GameObject nearestEnemy=null;
foreach(敌人中的游戏对象敌人)
{
浮动距离敌人=矢量3.距离(变换.位置,敌人.变换.位置);
if(与敌人的距离<最短距离)
{
最短距离=与敌人的距离;
近亲=敌人;
}
}

如果(nearestEnemy!=null&&shortestDistanceGameObject.FindGameObjectsWithTag对性能有更大的影响,我建议您创建一个圆形碰撞器2d并将其设置为触发器,当调用OnTiggerEnter2D时,您可以抓取敌人并升起一个标志,以便在调用OnTiggerExit2D后不会触发其他敌人你可以开始寻找另一个敌人,或者选择一个仍然在对撞机半径内的敌人

private bool _foundEnemy;
private Enemy _currentEnemy;

private void OnTriggerEnter2D(Collider2D collision)
{
    if (_foundEnemy) return;

    _currentEnemy = collision.GetComponent<Enemy>();
    // your code here
    _foundEnemy = true;
}

private void OnTriggerExit2D(Collider2D collision)
{
    if(_currentEnemy!=null && collision.GetComponent<Enemy>() == _currentEnemy)
        _foundEnemy = false;
}
privatebool\u;
私人敌人(私人敌人);;
私有无效OnTiggerEnter2D(已碰撞R2D碰撞)
{
如果敌人回来了;
_CurrentForeign=collision.GetComponent();
//你的代码在这里
_发现敌人=正确;
}
私有无效OnTriggerExit2D(已碰撞R2D碰撞)
{
if(\u currentEquire!=null&&collision.GetComponent()=\u currentEquire)
_发现敌人=虚假;
}

GameObject.FindGameObjectsSwithTag对性能有更大的影响,我建议您创建一个圆形碰撞器2d并将其设置为触发,当调用OnTiggerEnter2D时,您可以抓取敌人并升起一个标志,以便在这之后不会触发其他敌人,当对该敌人调用OnTiggerExit2D时,您可以开始寻找敌人另一个敌人或选择一个仍然在碰撞器半径内的敌人

private bool _foundEnemy;
private Enemy _currentEnemy;

private void OnTriggerEnter2D(Collider2D collision)
{
    if (_foundEnemy) return;

    _currentEnemy = collision.GetComponent<Enemy>();
    // your code here
    _foundEnemy = true;
}

private void OnTriggerExit2D(Collider2D collision)
{
    if(_currentEnemy!=null && collision.GetComponent<Enemy>() == _currentEnemy)
        _foundEnemy = false;
}
privatebool\u;
私人敌人(私人敌人);;
私有无效OnTiggerEnter2D(已碰撞R2D碰撞)
{
如果敌人回来了;
_CurrentForeign=collision.GetComponent();
//你的代码在这里
_发现敌人=正确;
}
私有无效OnTriggerExit2D(已碰撞R2D碰撞)
{
if(\u currentEquire!=null&&collision.GetComponent()=\u currentEquire)
_发现敌人=虚假;
}

您必须在UpdateTarget中包含一个测试,该测试应首先检查Nearestnemy是否仍在范围内,在这种情况下,退出该函数,否则搜索新目标

逻辑应该是这样的:

//keep old target?
if(nearestEnemy != null)
{
  //calculate distance of current target here..
  if(distance <= range)
     return; //keep this enemy as target
}
//here comes your code for finding a new target...
//是否保留旧目标?
if(nearestnemy!=null)
{
//在此计算当前目标的距离。。

如果(距离您必须在UpdateTarget中包含一个测试,它应该首先检查Nearestnemy是否仍在范围内,在这种情况下退出该函数,否则搜索新目标

逻辑应该是这样的:

//keep old target?
if(nearestEnemy != null)
{
  //calculate distance of current target here..
  if(distance <= range)
     return; //keep this enemy as target
}
//here comes your code for finding a new target...
//是否保留旧目标?
if(nearestnemy!=null)
{
//在此计算当前目标的距离。。

如果(distance您不完全清楚您想要实现什么行为,但似乎是锁定到一个目标直到它死掉,然后才切换到另一个目标。这是代码中的一个简单修复方法;但是我发现了几个其他问题:

  • 冗余代码,如块和变量
  • 这几乎是一个如何失败的例子
  • 您不需要像其他答案所显示的那样使用“一个或另一个”方法。您可以使用一个简单的
    布尔标志作为开关来获得这两种行为
  • 这里提供了一些解释所有这些事情的注释代码,希望您能从中借鉴:

    //Defines how to get and compare distance; used during sorting
    public class DistanceComparer<T> : IComparer<T> where T : GameObject {
       public int Compare(T a, T b) {
           return Vector3.Distance(a.transform.position, b.transform.position);
       }
    }
    
    public var bool lockToTargetUntilDead = true; //Should lock to target till it's dead (true)? Or switch to nearest if the nearest changes (false)?
    
    //Finds nearest enemy
    GameObject FindNearestEnemy() {
        var enemies = GameObject.FindGameObjectsWithTag(enemyTag);
        if (enemies==null || enemies.Length==0) return null; //No enemies anywhere
        Array.Sort(enemies, new DistanceComparer()); //Sort enemies by distance
        return enemies[0]; //Return closest enemy
    }
    
    //Determines if enemy is within range (Note: If enemy is null, it's not in range =P)
    bool IsWithinRange(GameObject enemy) {
        return enemy != null && Vector3.Distance(transform.position, enemy.transform.position) <= range;
    }
    
    //Updates target
    void UpdateTarget() {
        var nearestEnemy = FindNearestEnemy();
        if(!IsWithinRange(nearestEnemy)) { //No enemies within range...
            if(target != null) target = null; //Forget current target.
            return; //Return-early.
        }
        if(lockToTargetUntilDead && target!=null) return; //If locking to current target and it ain't dead yet, return-early
        target = nearestEnemy; //If not locking to target, or doesn't have a target, new target!
    }
    
    void Start () {
        InvokeRepeating("UpdateTarget", 0f , 0.5f );
    }
    
    //定义如何获取和比较距离;在排序过程中使用
    公共类DistanceComparer:IComparer其中T:GameObject{
    公共整数比较(TA,TB){
    返回向量3.距离(a.变换位置,b.变换位置);
    }
    }
    public var bool lockToTargetUntilDead=true;//应该锁定到目标直到它死(true)?或者如果最近的更改(false)则切换到最近的?
    //找到最近的敌人
    GameObject FindNearestEnemy(){
    var敌人=GameObject.FindGameObjectsWithTag(enemyTag);
    如果(敌人==null | |敌人.长度==0)返回null;//任何地方都没有敌人
    Sort(敌人,新距离比较器());//按距离对敌人排序
    返回敌人[0];//返回最近的敌人
    }
    //确定敌人是否在射程内(注意:如果敌人为空,则不在射程=P内)
    布尔在范围内(游戏对象敌人){
    
    return敌军!=null&&Vector3.Distance(transform.position,敌方.transform.position)您不完全清楚要实现什么行为,但似乎要锁定目标直到其死亡,然后才切换到另一个目标。这是代码中的一个简单修复方法;不过我发现了几个其他问题:

  • 冗余代码,如块和变量
  • 这几乎是一个如何失败的例子
  • 您不需要像其他答案所显示的那样使用“一个或另一个”方法。您可以使用一个简单的
    布尔标志作为开关来获得这两种行为
  • 这里提供了一些解释所有这些事情的注释代码,希望您能从中借鉴:

    //Defines how to get and compare distance; used during sorting
    public class DistanceComparer<T> : IComparer<T> where T : GameObject {
       public int Compare(T a, T b) {
           return Vector3.Distance(a.transform.position, b.transform.position);
       }
    }
    
    public var bool lockToTargetUntilDead = true; //Should lock to target till it's dead (true)? Or switch to nearest if the nearest changes (false)?
    
    //Finds nearest enemy
    GameObject FindNearestEnemy() {
        var enemies = GameObject.FindGameObjectsWithTag(enemyTag);
        if (enemies==null || enemies.Length==0) return null; //No enemies anywhere
        Array.Sort(enemies, new DistanceComparer()); //Sort enemies by distance
        return enemies[0]; //Return closest enemy
    }
    
    //Determines if enemy is within range (Note: If enemy is null, it's not in range =P)
    bool IsWithinRange(GameObject enemy) {
        return enemy != null && Vector3.Distance(transform.position, enemy.transform.position) <= range;
    }
    
    //Updates target
    void UpdateTarget() {
        var nearestEnemy = FindNearestEnemy();
        if(!IsWithinRange(nearestEnemy)) { //No enemies within range...
            if(target != null) target = null; //Forget current target.
            return; //Return-early.
        }
        if(lockToTargetUntilDead && target!=null) return; //If locking to current target and it ain't dead yet, return-early
        target = nearestEnemy; //If not locking to target, or doesn't have a target, new target!
    }
    
    void Start () {
        InvokeRepeating("UpdateTarget", 0f , 0.5f );
    }
    
    //定义如何获取和比较距离;在排序过程中使用
    公共类DistanceComparer:IComparer其中T:GameObject{
    公共整数比较(TA,TB){
    返回向量3.距离(a.变换位置,b.变换位置);
    }
    }
    public var bool lockToTargetUntilDead=true;//应该锁定到目标直到它死(true)?或者如果最近的更改(false)则切换到最近的?
    //