产生所需数量的预制件
Spawning the desired number of prefabs
如何使用以下代码实例化所需数量的预制件?我需要生成一个(而且只有一个)玩家预制件、X 个敌人和一个(而且只有一个)结束游戏预制件。
private void GenerateEnemies(int xMax, int zMax)
{
GameObject landscape = new GameObject("ENEMIES");
for (int z = 0; z < zMax; z++)
{
for (int x = 0; x < xMax; x++)
{
randNum = Random.Range(0, 100);
if (randNum < 10 )
{
Instantiate(enemy1, new Vector3(x * 10, 0, z * 10), Quaternion.Euler(0, 0, 0));//, landscape.transform);
}
else if (randNum < 20)
{
Instantiate(enemy2, new Vector3(x * 10, 0, z * 10), Quaternion.Euler(0, 0, 0));//, landscape.transform);
}
else if (randNum < 30)
{
Instantiate(enemy3, new Vector3(x * 10, 0, z * 10), Quaternion.Euler(0, 0, 0));//, landscape.transform);
}
else if (randNum < 40)
{
Instantiate(enemy4, new Vector3(x * 10, 0, z * 10), Quaternion.Euler(0, 0, 0));//, landscape.transform);
}
else if (randNum < 50)
{
Instantiate(enemy5, new Vector3(x * 10, 0, z * 10), Quaternion.Euler(0, 0, 0));//, landscape.transform);
}
}
}
}
好吧,只需在循环外做一次性的事情!
还有
randNum = Random.Range(0, 100);
然后你只使用 5 种不同的情况,并且只有当值较小时 50
(所以大约一半的情况根本没有发生......)。如果这是有意的.. ok-ish ..否则我宁愿使用列表和随机索引:
// HINT: Rather have a list for your prefabs
// this shrinks your code a lot
public List<GameObject/*or whatever type*/> eneymPrefabs = new List<GameObject>();
public Gamebject playerPrefab;
public GameObject endGamePrefab;
private void GenerateEnemies(int xMax, int zMax)
{
var landscape = new GameObject("ENEMIES");
// Do these only once
// store the references in case you need them later
var player = Instantiate(playerPrefab);
var endGame = Instantiate(endGamePrefab);
for (int z = 0; z < zMax; z++)
{
for (int x = 0; x < xMax; x++)
{
// simply pick a random index from the prefab list
int randIndex = Random.Range(0, eneymPrefabs.Count);
// and get the according random prefab
var enemyPrefab = enemyPrefabs[randIndex];
if(enemyPrefab) Instantiate(enemyPrefab, new Vector3(x * 10, 0, z * 10), Quaternion.identity /*, landscape.transform*/);
}
}
}
或者Draco18s提到的加权列表的例子
[Serializable]
public class WeightedPrefab
{
public GameObject Prefab;
public int Weight = 1;
}
public List<WeightedPrefab> weightedEnemyPrefabs;
public Gamebject playerPrefab;
public GameObject endGamePrefab;
private void GenerateEnemies(int xMax, int zMax)
{
// create a temp list using the weights and random index on this one
var enemyPrefabs = new List<GameObject>();
foreach(var item in weightedEnemyPrefabs)
{
for(var i = 0; i < item.Weight; i++)
{
enemyPrefabs.Add(item.Prefab);
}
}
// Rest stays the same
var landscape = new GameObject("ENEMIES");
// Do these only once
// store the references in case you need them later
var player = Instantiate(playerPrefab);
var endGame = Instantiate(endGamePrefab);
for (int z = 0; z < zMax; z++)
{
for (int x = 0; x < xMax; x++)
{
// simply pick a random index from the prefab list
int randIndex = Random.Range(0, eneymPrefabs.Count);
// and get the according random prefab
var enemyPrefab = enemyPrefabs[randIndex];
if(enemyPrefab) Instantiate(enemyPrefab, new Vector3(x * 10, 0, z * 10), Quaternion.identity /*, landscape.transform*/);
}
}
}
如果不是在所有情况下都有意实例化敌人,您仍然可以使用这两种方法,只需将预制参考留空 →对于该索引,不会实例化任何内容。
the enemy and end game should be part of the grid
在这种情况下,我会先将整个网格组合写入一个列表中。从这个列表中随机选择两个条目,并将玩家和 endGame 放在那里。然后挡住这两个网格位置,不要在那里生成敌人:
[Serializable]
public class WeightedPrefab
{
public GameObject Prefab;
public int Weight = 1;
}
public List<WeightedPrefab> weightedEnemyPrefabs;
public Gamebject playerPrefab;
public GameObject endGamePrefab;
private void GenerateEnemies(int xMax, int zMax)
{
// Create a list of all awailable grid positions
var gridPositions = new List<Vector2Int>();
for (int z = 0; z < zMax; z++)
{
for (int x = 0; x < xMax; x++)
{
gridPositions.Add(new Vector2Int(x,z));
}
}
// pick the two random positions for player and endgame
var playerPosIndex = Random.Range(0, gridPositions.Count);
var playerPos = gridPositions[playerPosIndex];
gridPositions.RemoveAt(playerPosIndex);
var endGamePosIndex = Random.Range(0, gridPositions.Count);
var endGamePos = gridPositions[endGamePosIndex];
gridPositions.RemoveAt(endGamePosIndex);
// create a temp list using the weights and random index on this one
var enemyPrefabs = new List<GameObject>();
foreach(var item in weightedEnemyPrefabs)
{
for(var i = 0; i < item.Weight; i++)
{
enemyPrefabs.Add(item.Prefab);
}
}
var landscape = new GameObject("ENEMIES");
// Do these only once
// store the references in case you need them later
var player = Instantiate(playerPrefab, new Vector3(payerPos.x * 10, 0, playerPos.y * 10), Quaternion.identity /*, landscape.transform*/);
var endGame = Instantiate(endGamePrefab, new Vector3(endGamePos.x * 10, 0, endGamePos.y * 10), Quaternion.identity /*, landscape.transform*/);
for (int z = 0; z < zMax; z++)
{
for (int x = 0; x < xMax; x++)
{
// Now simply ignore the playerPos and endGamePos
if(x == playerPos.x && z == playerPos.y) continue;
if(x == endGamePos.x && z == endGamePos.y) continue;
// pick a random index from the prefab list
int randIndex = Random.Range(0, eneymPrefabs.Count);
// and get the according random prefab
var enemyPrefab = enemyPrefabs[randIndex];
// do nothing if enemyPrefab is null otherwise instantiate
if(enemyPrefab) Instantiate(enemyPrefab, new Vector3(x * 10, 0, z * 10), Quaternion.identity /*, landscape.transform*/);
}
}
}
考虑这段代码:
for (int z = 0; z < zMax; z++)
{
for (int x = 0; x < xMax; x++)
{
randNum = Random.Range(1, 11);
if (randNum == 1) Instantiate(enemy1, new Vector3(x * 10, 0, z * 10), Quaternion.Euler(0, 0, 0));//, landscape.transform);
if (randNum == 2) Instantiate(enemy2, new Vector3(x * 10, 0, z * 10), Quaternion.Euler(0, 0, 0));//, landscape.transform);
if (randNum == 3) Instantiate(enemy3, new Vector3(x * 10, 0, z * 10), Quaternion.Euler(0, 0, 0));//, landscape.transform);
if (randNum == 4) Instantiate(enemy4, new Vector3(x * 10, 0, z * 10), Quaternion.Euler(0, 0, 0));//, landscape.transform);
if (randNum == 5) Instantiate(enemy5, new Vector3(x * 10, 0, z * 10), Quaternion.Euler(0, 0, 0));//, landscape.transform);
}
}
应该清楚这段代码与您发布的代码所做的相同。
还应该清楚这更好,因为它总是 运行 以相同的速度(在游戏中随机 运行 慢通常很糟糕)
如何使用以下代码实例化所需数量的预制件?我需要生成一个(而且只有一个)玩家预制件、X 个敌人和一个(而且只有一个)结束游戏预制件。
private void GenerateEnemies(int xMax, int zMax)
{
GameObject landscape = new GameObject("ENEMIES");
for (int z = 0; z < zMax; z++)
{
for (int x = 0; x < xMax; x++)
{
randNum = Random.Range(0, 100);
if (randNum < 10 )
{
Instantiate(enemy1, new Vector3(x * 10, 0, z * 10), Quaternion.Euler(0, 0, 0));//, landscape.transform);
}
else if (randNum < 20)
{
Instantiate(enemy2, new Vector3(x * 10, 0, z * 10), Quaternion.Euler(0, 0, 0));//, landscape.transform);
}
else if (randNum < 30)
{
Instantiate(enemy3, new Vector3(x * 10, 0, z * 10), Quaternion.Euler(0, 0, 0));//, landscape.transform);
}
else if (randNum < 40)
{
Instantiate(enemy4, new Vector3(x * 10, 0, z * 10), Quaternion.Euler(0, 0, 0));//, landscape.transform);
}
else if (randNum < 50)
{
Instantiate(enemy5, new Vector3(x * 10, 0, z * 10), Quaternion.Euler(0, 0, 0));//, landscape.transform);
}
}
}
}
好吧,只需在循环外做一次性的事情!
还有
randNum = Random.Range(0, 100);
然后你只使用 5 种不同的情况,并且只有当值较小时 50
(所以大约一半的情况根本没有发生......)。如果这是有意的.. ok-ish ..否则我宁愿使用列表和随机索引:
// HINT: Rather have a list for your prefabs
// this shrinks your code a lot
public List<GameObject/*or whatever type*/> eneymPrefabs = new List<GameObject>();
public Gamebject playerPrefab;
public GameObject endGamePrefab;
private void GenerateEnemies(int xMax, int zMax)
{
var landscape = new GameObject("ENEMIES");
// Do these only once
// store the references in case you need them later
var player = Instantiate(playerPrefab);
var endGame = Instantiate(endGamePrefab);
for (int z = 0; z < zMax; z++)
{
for (int x = 0; x < xMax; x++)
{
// simply pick a random index from the prefab list
int randIndex = Random.Range(0, eneymPrefabs.Count);
// and get the according random prefab
var enemyPrefab = enemyPrefabs[randIndex];
if(enemyPrefab) Instantiate(enemyPrefab, new Vector3(x * 10, 0, z * 10), Quaternion.identity /*, landscape.transform*/);
}
}
}
或者Draco18s提到的加权列表的例子
[Serializable]
public class WeightedPrefab
{
public GameObject Prefab;
public int Weight = 1;
}
public List<WeightedPrefab> weightedEnemyPrefabs;
public Gamebject playerPrefab;
public GameObject endGamePrefab;
private void GenerateEnemies(int xMax, int zMax)
{
// create a temp list using the weights and random index on this one
var enemyPrefabs = new List<GameObject>();
foreach(var item in weightedEnemyPrefabs)
{
for(var i = 0; i < item.Weight; i++)
{
enemyPrefabs.Add(item.Prefab);
}
}
// Rest stays the same
var landscape = new GameObject("ENEMIES");
// Do these only once
// store the references in case you need them later
var player = Instantiate(playerPrefab);
var endGame = Instantiate(endGamePrefab);
for (int z = 0; z < zMax; z++)
{
for (int x = 0; x < xMax; x++)
{
// simply pick a random index from the prefab list
int randIndex = Random.Range(0, eneymPrefabs.Count);
// and get the according random prefab
var enemyPrefab = enemyPrefabs[randIndex];
if(enemyPrefab) Instantiate(enemyPrefab, new Vector3(x * 10, 0, z * 10), Quaternion.identity /*, landscape.transform*/);
}
}
}
如果不是在所有情况下都有意实例化敌人,您仍然可以使用这两种方法,只需将预制参考留空 →对于该索引,不会实例化任何内容。
the enemy and end game should be part of the grid
在这种情况下,我会先将整个网格组合写入一个列表中。从这个列表中随机选择两个条目,并将玩家和 endGame 放在那里。然后挡住这两个网格位置,不要在那里生成敌人:
[Serializable]
public class WeightedPrefab
{
public GameObject Prefab;
public int Weight = 1;
}
public List<WeightedPrefab> weightedEnemyPrefabs;
public Gamebject playerPrefab;
public GameObject endGamePrefab;
private void GenerateEnemies(int xMax, int zMax)
{
// Create a list of all awailable grid positions
var gridPositions = new List<Vector2Int>();
for (int z = 0; z < zMax; z++)
{
for (int x = 0; x < xMax; x++)
{
gridPositions.Add(new Vector2Int(x,z));
}
}
// pick the two random positions for player and endgame
var playerPosIndex = Random.Range(0, gridPositions.Count);
var playerPos = gridPositions[playerPosIndex];
gridPositions.RemoveAt(playerPosIndex);
var endGamePosIndex = Random.Range(0, gridPositions.Count);
var endGamePos = gridPositions[endGamePosIndex];
gridPositions.RemoveAt(endGamePosIndex);
// create a temp list using the weights and random index on this one
var enemyPrefabs = new List<GameObject>();
foreach(var item in weightedEnemyPrefabs)
{
for(var i = 0; i < item.Weight; i++)
{
enemyPrefabs.Add(item.Prefab);
}
}
var landscape = new GameObject("ENEMIES");
// Do these only once
// store the references in case you need them later
var player = Instantiate(playerPrefab, new Vector3(payerPos.x * 10, 0, playerPos.y * 10), Quaternion.identity /*, landscape.transform*/);
var endGame = Instantiate(endGamePrefab, new Vector3(endGamePos.x * 10, 0, endGamePos.y * 10), Quaternion.identity /*, landscape.transform*/);
for (int z = 0; z < zMax; z++)
{
for (int x = 0; x < xMax; x++)
{
// Now simply ignore the playerPos and endGamePos
if(x == playerPos.x && z == playerPos.y) continue;
if(x == endGamePos.x && z == endGamePos.y) continue;
// pick a random index from the prefab list
int randIndex = Random.Range(0, eneymPrefabs.Count);
// and get the according random prefab
var enemyPrefab = enemyPrefabs[randIndex];
// do nothing if enemyPrefab is null otherwise instantiate
if(enemyPrefab) Instantiate(enemyPrefab, new Vector3(x * 10, 0, z * 10), Quaternion.identity /*, landscape.transform*/);
}
}
}
考虑这段代码:
for (int z = 0; z < zMax; z++)
{
for (int x = 0; x < xMax; x++)
{
randNum = Random.Range(1, 11);
if (randNum == 1) Instantiate(enemy1, new Vector3(x * 10, 0, z * 10), Quaternion.Euler(0, 0, 0));//, landscape.transform);
if (randNum == 2) Instantiate(enemy2, new Vector3(x * 10, 0, z * 10), Quaternion.Euler(0, 0, 0));//, landscape.transform);
if (randNum == 3) Instantiate(enemy3, new Vector3(x * 10, 0, z * 10), Quaternion.Euler(0, 0, 0));//, landscape.transform);
if (randNum == 4) Instantiate(enemy4, new Vector3(x * 10, 0, z * 10), Quaternion.Euler(0, 0, 0));//, landscape.transform);
if (randNum == 5) Instantiate(enemy5, new Vector3(x * 10, 0, z * 10), Quaternion.Euler(0, 0, 0));//, landscape.transform);
}
}
应该清楚这段代码与您发布的代码所做的相同。
还应该清楚这更好,因为它总是 运行 以相同的速度(在游戏中随机 运行 慢通常很糟糕)