我正在团结一致进行塔防游戏,但我被卡住了。我希望我的枪或炮塔能够面对敌人,直到他们超出射程,但每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;
}
}
答案 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)
你并不完全清楚你想要实现什么样的行为,但它似乎是锁定目标直到它死了,然后才切换到另一个目标。这是您代码中的一个简单修复;但是我发现了其他一些问题:
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 );
}