在c#游戏代码中需要帮助

时间:2017-10-28 18:34:23

标签: c# unity3d

我正在团结一致进行塔防游戏,但我被卡住了。我希望我的枪或炮塔能够面对敌人,直到他们超出射程,但每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; 
    }        
}

3 个答案:

答案 0 :(得分:2)

你必须在UpdateTarget中包含一个测试,该测试应首先检查,如果nearestEnemy仍在该范围内,并且在这种情况下退出该函数,否则搜索新目标。

逻辑看起来应该是这样的:

//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...

答案 1 :(得分:1)

GameObject.FindGameObjectsWithTag对性能的影响更大,我建议你创建一个圆形对撞机2d并将其设置为触发,当调用OnTriggerEnter2D时,你可以获取敌人并举起一个旗帜,这样其他敌人就不会被触发之后,当对该敌人召唤OnTriggerExit2D时,你可以开始寻找另一个敌人,或者选择仍在该对手半径范围内的敌人。

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;
}

答案 2 :(得分:1)

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

  1. 冗余代码,如块和变量。
  2. 几乎是 失败 如何关注Single Responsibility Principle的示例。
  3. 您不需要“one or other”方法,因为其他答案正在显示。您可以使用简单boolean flag作为切换来获取 两种行为
  4. 这里有一些注释代码可以解释所有这些事情,希望您可以从参考资料中学习:

    //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 );
    }