2016-04-30 44 views
-1

我有在我的遊戲中散佈在地形上的動物的產卵者。這個想法是隻有當一個玩家在產卵者的範圍內時動物纔會產卵,但是如果在產卵者的近距離範圍內有太多的動物則不會產生動物。這是我迄今爲止所做的,但現在我有點卡住了。任何人都可以給我一些關於以下幾點的指導:C#動物Spawner邏輯 - 需要建議

  • 生成的機率是否正確計算?例如以10%和90%的產卵率創造兩個動物實際上會使動物A有10%的機會產卵,animalB有90%的機會或者我的數學錯誤?
  • 我的半徑計算是否正確?
  • 最重要的是:我可以改善它嗎?

代碼:

[System.Serializable] 
public class SpawnableAnimal 
{ 
public string AnimalName; 
public float spawnWeight; 

public float spawnPercentage; 
} 

public class AnimalSpawner : MonoBehaviour { 

public float maxSpawnRadius = 1000.0f; 
public float noSpawnRadius = 700.0f; 

public GameObject spawnedAnimal; 

public SpawnableAnimal[] spawnableAnimals; 

void Start() { 
    System.Random rand = new System.Random(); 
    int randInt = rand.Next(0, 100); 

    float startTime = randInt/100f; 
    float repeatTime = randInt/100f; 
    InvokeRepeating("ReadyToSpawn", startTime, (60.0f + repeatTime)); 
} 

void ReadyToSpawn() 
{ 
    Debug.Log("Ready to spawn"); 
    bool canSpawn = true; 

    GameObject[] players = GameObject.FindGameObjectsWithTag("Player"); 
    GameObject[] animals = GameObject.FindGameObjectsWithTag("Animal"); 
    for(int i = 0; i < players.Length; i++) 
    { 
     if (Vector3.Distance(this.transform.position, players[i].transform.position) > maxSpawnRadius) 
      canSpawn = false; 

     if (Vector3.Distance(this.transform.position, players[i].transform.position) < noSpawnRadius) 
      canSpawn = false; 
    } 

    if (players.Length < 1) 
     canSpawn = false; 

    if (spawnedAnimal != null) 
     canSpawn = false; 

    if (canSpawn) 
     SpawnAnimal(); 
} 

void SpawnAnimal() 
{ 
    System.Random rand = new System.Random(); 
    double x = rand.NextDouble(); 

    var totalWeight = spawnableAnimals.Select(a => a.spawnWeight).Sum(); 

    for(int i = 0; i < spawnableAnimals.Length; i++) 
    { 
     float spawnPercentage = spawnableAnimals[i].spawnWeight/totalWeight; 

     if(x < spawnPercentage) 
     { 
      InstantiateAnimal(i); 
      return; 
     } 

     x -= spawnPercentage; 
    } 
} 

void InstantiateAnimal(int animalToSpawn) 
{ 
    if (animalToSpawn != -1) 
     spawnedAnimal = GameObject.Find("AnimalManager").GetComponent<AnimalManager>().SpawnAnimal(spawnableAnimals[animalToSpawn].AnimalName, this.transform.position, this.transform.rotation); 
    else Debug.Log("No animal to spawn!"); 
} 

}

+0

你應該在http://codereview.stackexchange.com/上發帖,這些問題在這裏脫離主題 – Stephen

+0

謝謝!甚至不知道codereview.stackexchange.com –

回答

1
Vector3.Distance(this.transform.position, players[i].transform.position) 

這些位置在同一個空間嗎? Vector3.Distance(x, y)的意思是|x - y|?如果是這樣,那麼對我來說計算看起來不錯。

SpawnAnimal似乎很奇怪。我不確定它在做什麼。如果你能解釋你的想法,那麼我可能會理解它。

我會給每隻動物分配一個重量。這個數字是任意的,但它們的相對大小很重要。如果貓的體重爲100,而狗的體重爲1000,那麼狗的產卵率比貓的高10倍。

另外:爲什麼重量而不是百分比?如果你定義貓有10%的產卵機會並且有90%的產卵機會,然後你增加沙鼠,剩下的沙鼠分配的比例是多少?百分比必須加1,所以你必須調整所有其他動物的百分比來騰出空間。如果我們使用體重,100只貓和1000只狗,那麼我們可以添加重量爲500的沙鼠,我們知道沙鼠的產卵量是貓的5倍,是狗的一半,不需要調整。

讓我們假設你在[0,1)中產生一個隨機數x(這可以用NextDouble()來完成)。

我們想爲每個動物分配一個間隔[0,1),這個動物的體重與體重成正比。首先找到總重量。

var totalWeight = spawnableAnimals.Select(a => a.Weight).Sum(); 

由此我們可以爲每隻動物分配一個百分比a.Weight/totalWeight。這些百分比加1,因此您可以在[0,1)區間內分配這些百分比。 Pi是從索引的動物組A其中0 <= i < nn|A|(即動物的數量)產生動物Ai的概率。

0.0 0.1 0.2 0.3 … 1.0 
[ P1 )[  P2 )[ … Pn) 

現在,你只需要確定適合該區間x謊言,這是產卵動物。這是一個程序算法來做到這一點。

  1. 初始化A = the set of animalsi = 0x = NextDouble()n = |A|
  2. 如果i < n
    • 然後:如果x < Pi
      • 然後:停止和產卵Ai
      • 否則:
        1. 減法Pix
        2. 增量i
        3. 轉到(2)。
    • 其他:停止沒有動物產卵。

ith間隔(0 <= i < n),其中求和是通過0 <= j < i索引是:

  1. ΣP(j-1) <= x < ΣP(j-1) + Pi(參見實施例的表)
  2. ΣP(j-1) - ΣP(j-1) <= x - ΣP(j-1) < ΣP(j-1) + Pi - ΣP(j-1)(減去ΣP(j-1)
  3. 0 <= x - ΣP(j-1) < Pi(簡化)

    • x - ΣP(j-1)是通過累加扣除來實現的。
    • 0 <= x通過0 <= NextDouble() < 1並且如果x >= Pi然後x - Pi >= 0(循環不變)來實現。
    • 因此,我們只需要測試x < Pi

注意:這依賴於具有均勻分佈的隨機數發生器。

+0

我真的很感謝這樣的答案!像這樣的答案有助於我理解並學習新方法來處理這些事情,而不僅僅是給我複製和粘貼代碼。我嘗試根據你的解釋用一種新方法替換SpawnAnimal方法。上述調整大致上是你的意思嗎? –

+0

@MinganBeyleveld不完全。當我說「暫停」時,您需要結束算法,這意味着循環中的「break」或函數的「返回」或任何適當的操作。我還修復了算法中幾個缺失的部分(邊界檢查'i erisco

+0

非常感謝您的幫助!我再次更新了代碼(希望正確地做)? –

0

你正在做的整數除法這裏:

float startTime = randInt/100 

我想你想要的是:

float startTime = randInt/100f 

你得到重生的機會 「逆轉」:

if(randInt <= spawnableAnimals[i].spawnChance 

應該是:

if(randInt >= spawnableAnimals[i].spawnChance 

然而,這並不完全解決了這一切,這是因爲:

arraySum += randInt; 

是做一樣的:

break; 

因此,如果spawnableAnimals中的第一個元素的spawnChance爲10%,並且spawnableAnimals中的第二個元素的spawnChance爲90%,那麼您將以第一個10%的分配結束,而90%* 90%=第二個是81%,因爲第二個元素只在第一個元素失敗時才被嘗試。