C# Unity-网格生成和平铺邻居,我如何读取它们?
因此,目前我正在制作一个小游戏,我正在使用细胞自动机生成世界 所以我的问题来了。 我试图找到一种方法来阅读和分配瓷砖的邻居 将创建一个平铺,并将其4个邻居(上面、右边、左边和下面)分配给它,它可以通过代码访问这些平铺。(世界一代所需) 我不想使用Rayscast或Spheres来检测邻居,因为它会降低性能并很快变得混乱 几周来我一直在努力寻找解决问题的方法,但我不明白该如何解决这个问题 这是我给世界一代的代码C# Unity-网格生成和平铺邻居,我如何读取它们?,c#,unity3d,grid,neighbours,C#,Unity3d,Grid,Neighbours,因此,目前我正在制作一个小游戏,我正在使用细胞自动机生成世界 所以我的问题来了。 我试图找到一种方法来阅读和分配瓷砖的邻居 将创建一个平铺,并将其4个邻居(上面、右边、左边和下面)分配给它,它可以通过代码访问这些平铺。(世界一代所需) 我不想使用Rayscast或Spheres来检测邻居,因为它会降低性能并很快变得混乱 几周来我一直在努力寻找解决问题的方法,但我不明白该如何解决这个问题 这是我给世界一代的代码 public class WorldGenerator : MonoBehaviour
public class WorldGenerator : MonoBehaviour
{
public int mapSize;
public string worldSeed;
public bool useRandomSeed;
[Range(0, 100)]
public int percentOfMapIsLand;
public GameObject tile;
public List<GameObject> tiles;
public int[,] mapFilled;
// Start is called before the first frame update
void Start()
{
RandomlyFillMap();
GenerateStartingGrid();
AssignTileNeighbors();
}
void RandomlyFillMap()
{
mapFilled = new int[mapSize, mapSize];
if (useRandomSeed) { worldSeed = Time.time.ToString(); }
System.Random randomNumber = new System.Random(worldSeed.GetHashCode());
for (int x = 0; x < mapSize; x++)
{
for (int y = 0; y < mapSize; y++)
{
mapFilled[x, y] = (randomNumber.Next(0, 100) < percentOfMapIsLand) ? 1 : 0;
}
}
}
void GenerateStartingGrid()
{
for (int x = 0; x < mapSize; x++)
{
for (int y = 0; y < mapSize; y++)
{
if( mapFilled[x,y] == 0)
{
Vector3 tilePosition = new Vector3(-mapSize / 2 + x, 0, -mapSize / 2 + y);
GameObject newTile = Instantiate(tile, tilePosition, Quaternion.Euler(Vector3.right * 90f)) as GameObject;
newTile.transform.SetParent(transform, false);
tiles.Add(newTile);
}
else { continue; }
}
}
}
void AssignTileNeighbors()
{
for (int x = 0; x < mapSize; x++)
{
for (int y = 0; y < mapSize; y++)
{
//ASIGN NEIGHBOURS HERE//
}
}
}
}
首先,您不仅需要存储
int
值,还需要存储您的分幅,因此我会将值与分幅一起存储
public class Tile : MonoBehaviour
{
public bool IsLand;
// What you have you have ;)
public Vector2Int GridPosition;
public Tile neighbor_UP;
public Tile neighbor_RIGHT;
public Tile neighbor_LEFT;
public Tile neighbor_DOWN;
}
那么让我们假设网格看起来像
Y
^ 03 13 23 33
| 02 12 22 32
| 01 11 21 31
| 00 10 20 30
----------> X
其中第一个值是x
第二个值是y
和mapSize=4
,如您所见,您可以通过这样轻松地浏览磁贴(示例当前磁贴是21
)
- 向上:
,示例:y+1
→ <代码>2221
- 向下:
,示例:y-1
→ <代码>2021
- 左:
,示例:x-1
→ <代码>1221
- 右:
,示例:x+1
→ <代码>3221
public class WorldGenerator : MonoBehaviour
{
public int mapSize;
public string worldSeed;
public bool useRandomSeed;
[Range(0, 100)]
public int percentOfMapIsLand;
// Make your prefabs of type Tile instead
public Tile tile;
// instead store Tile instances
public Tile[,] mapFilled;
void Start()
{
RandomlyFillMap();
AssignTileNeighbors();
}
void RandomlyFillMap()
{
// In one go cretae the random values and all tile instances
mapFilled = new Tile[mapSize, mapSize];
if (useRandomSeed)
{
worldSeed = Time.time.ToString();
}
var randomNumber = new System.Random(worldSeed.GetHashCode());
for (int x = 0; x < mapSize; x++)
{
for (int y = 0; y < mapSize; y++)
{
// To make things easier I would rather create all the tiles
// Even though this means a bit more overhead ONCE
// That's up to you ofcourse .. you could as well just not create them and then
// the according values in the neighbors would be not assigned
var isLand = randomNumber.Next(0, 100) < percentOfMapIsLand;
var tilePosition = new Vector3(-mapSize / 2 + x, 0, -mapSize / 2 + y);
var newTile = Instantiate(tile, tilePosition, Quaternion.Euler(Vector3.right * 90f));
newTile.transform.SetParent(transform, false);
newTile.IsLand = isLand;
newTile.GridPosition = new Vector2Int(x, y);
// Then simply disable the tiles you don't need
newTile.SetActive(isLand);
// And store them in the map
mapFilled[x, y] = newTile;
}
}
}
void AssignTileNeighbors()
{
for (int x = 0; x < mapSize; x++)
{
for (int y = 0; y < mapSize; y++)
{
// And now we just use the rules from before to get the neighbors
// for the edges the neighbors will stay unassigned
var tile = mapFilled[x,y];
// For each assignment we check whether the neighbor would still be within the map bounds
// if not, that means we are an edge tile and there exists no further neighbor
tile.neighbor_UP = y < mapSize - 1 ? mapFilled[x, y + 1];
tile.neighbor_DOWN = y > 0 ? mapFilled[x, y - 1];
tile.neighbor_LEFT = x > 0 ? mapFilled[x - 1, y];
tile.neighbor_RIGHT = x < mapSize - 1 ? mapFilled[x + 1, y];
}
}
}
公共类WorldGenerator:MonoBehavior
{
公共int地图大小;
公共种子;
公共bool用户和omseed;
[范围(0,100)]
马匹兰的公共单位百分比;
//将预制件改为瓷砖类型
公共瓷砖;
//而是存储平铺实例
公共瓷砖[,]已填充;
void Start()
{
RandomlyFillMap();
AssignTileNeighbors();
}
void RandomlyFillMap()
{
//一次性创建随机值和所有平铺实例
mapFilled=新磁贴[mapSize,mapSize];
if(useRandomSeed)
{
worldSeed=Time.Time.ToString();
}
var randomNumber=new System.Random(worldSeed.GetHashCode());
对于(int x=0;x0?映射填充[x,y-1];
tile.neighbor_LEFT=x>0?映射填充[x-1,y];
tile.neighbor_RIGHT=x
首先,您不仅需要存储int
值,还需要存储您的磁贴,因此我会将值与磁贴一起存储
public class Tile : MonoBehaviour
{
public bool IsLand;
// What you have you have ;)
public Vector2Int GridPosition;
public Tile neighbor_UP;
public Tile neighbor_RIGHT;
public Tile neighbor_LEFT;
public Tile neighbor_DOWN;
}
那么让我们假设网格看起来像
Y
^ 03 13 23 33
| 02 12 22 32
| 01 11 21 31
| 00 10 20 30
----------> X
其中第一个值是x
第二个值是y
和mapSize=4
,如您所见,您可以通过这样轻松地浏览磁贴(示例当前磁贴是21
)
- 向上:
,示例:y+1
→ <代码>2221
- 向下:
,示例:y-1
→ <代码>2021
- 左:
,示例:x-1
→ <代码>1221
- 右:
,示例:x+1
→ <代码>3221
public class WorldGenerator : MonoBehaviour
{
public int mapSize;
public string worldSeed;
public bool useRandomSeed;
[Range(0, 100)]
public int percentOfMapIsLand;
// Make your prefabs of type Tile instead
public Tile tile;
// instead store Tile instances
public Tile[,] mapFilled;
void Start()
{
RandomlyFillMap();
AssignTileNeighbors();
}
void RandomlyFillMap()
{
// In one go cretae the random values and all tile instances
mapFilled = new Tile[mapSize, mapSize];
if (useRandomSeed)
{
worldSeed = Time.time.ToString();
}
var randomNumber = new System.Random(worldSeed.GetHashCode());
for (int x = 0; x < mapSize; x++)
{
for (int y = 0; y < mapSize; y++)
{
// To make things easier I would rather create all the tiles
// Even though this means a bit more overhead ONCE
// That's up to you ofcourse .. you could as well just not create them and then
// the according values in the neighbors would be not assigned
var isLand = randomNumber.Next(0, 100) < percentOfMapIsLand;
var tilePosition = new Vector3(-mapSize / 2 + x, 0, -mapSize / 2 + y);
var newTile = Instantiate(tile, tilePosition, Quaternion.Euler(Vector3.right * 90f));
newTile.transform.SetParent(transform, false);
newTile.IsLand = isLand;
newTile.GridPosition = new Vector2Int(x, y);
// Then simply disable the tiles you don't need
newTile.SetActive(isLand);
// And store them in the map
mapFilled[x, y] = newTile;
}
}
}
void AssignTileNeighbors()
{
for (int x = 0; x < mapSize; x++)
{
for (int y = 0; y < mapSize; y++)
{
// And now we just use the rules from before to get the neighbors
// for the edges the neighbors will stay unassigned
var tile = mapFilled[x,y];
// For each assignment we check whether the neighbor would still be within the map bounds
// if not, that means we are an edge tile and there exists no further neighbor
tile.neighbor_UP = y < mapSize - 1 ? mapFilled[x, y + 1];
tile.neighbor_DOWN = y > 0 ? mapFilled[x, y - 1];
tile.neighbor_LEFT = x > 0 ? mapFilled[x - 1, y];
tile.neighbor_RIGHT = x < mapSize - 1 ? mapFilled[x + 1, y];
}
}
}
公共类WorldGenerator:MonoBehavior
{
公共int地图大小;
公共种子;
公共bool用户和omseed;
[范围(0,100)]
马匹兰的公共单位百分比;
//将预制件改为瓷砖类型
公共瓷砖;
//而是存储平铺实例
公共瓷砖[,]已填充;
void Start()
{
RandomlyFillMap();
AssignTileNeighbors();
}
void RandomlyFillMap()
{
//一次性创建随机值和所有平铺实例
mapFilled=新磁贴[mapSize,mapSize];
if(useRandomSeed)
{
worldSeed=Time.Time.ToString();
}
var randomNumber=new System.Random(worldSeed.GetHashCode());
对于(int x=0;x