2017-10-28 182 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