2016-04-30 83 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%,因为第二个元素只在第一个元素失败时才被尝试。