2017-10-28 145 views
0

我正在制作一个统一的塔防游戏,但我卡住了。我希望我的枪或炮塔面对敌人,直到他们超出范围,但每0.5秒后它会更新并面对其范围内的另一个敌人,尽管第一个敌人也在范围内。需要帮助在c#游戏代码

这里是我的代码:

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

也许一开始你应该检查是否已经有一个积极的目标,如果是的话,不要改变它。例如:if(target!= null && Vector3.Distance(transform.position,target.transform.position)<= range)return;'(注意:我不知道Unity,所以这可能不是正确的代码,但你会明白......) –

+0

是的,这听起来像是他们不希望它不断地改变目标,所以保持一个“主动目标”变量将是一个好方法。另外,我强烈建议添加一个包围炮塔范围的箱子对撞机,并用它来限制你必须搜索的敌人数量。 https://unity3d.com/learn/tutorials/topics/physics/colliders-triggers可能是有趣的。 Unity内置了强大的空间索引功能,所以很愚蠢的是不利用它。如果甚至有内置的“最近邻居”算法,我也不会感到惊讶。 – drsimonz

回答

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

你必须包括在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... 
+0

如果你有一个敌人靠近,那么它就成为最近的敌人,很好。你射击它,它停止移动(出于任何原因)。另一个敌人通过它靠近你,它将永远不会是最近的敌人,因为第一个敌人还在登记。 – Everts

1

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

  1. 冗余代码,如块和变量。
  2. 非常多的例子如何失败要遵循Single Responsibility Principle
  3. 您不需要“其中一个或另一个”方法,因为其他答案正在显示。你可以得到这两个行为与一个简单的boolean flag作为交换机。

这里是一些注释代码占所有这些东西,希望提供可以学习,从参考:

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

[协程将比重开销字符串查找调用更好(https://gamedev.stackexchange.com/a/120554/75627)。 – Draco18s

+0

@ Draco18s同意。但至少到目前为止,#NotMyProblem。我更感兴趣的是提供更一般的代码风格改进;我没有真正关注原始代码中的优化问题,或者对这些问题可以做的改进。 --- +1为OP和未来读者tho的有用参考;并且随意编辑和添加优化的东西,如果你觉得它(我不,ATM)。 – XenoRo