我想要的效果是:我在Unity,版本2020.3.31。里写了一个缩放地图,我希望在Unity检查器里改动一个值,就可以缩放整个地图(包括地板、障碍物、)
我做出来的效果:如图
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MapGenerator : MonoBehaviour
{
public float tilesize = 1;//建立可外控地图缩放(初始位1)
public Transform Quad;
public int seed;
public Transform mapPoint;
public Vector2 mapSize;
public Transform tilePresf;//建立瓦片(单个网格)
public Transform obsPresf;//建立障碍物的预制体
[Range(0, 1)]
public float obsPercent;
List coordsList;
[Range(0, 1)]
public float outinePercent;
Queue coordQueue;
Coord mapCenter;//地图中心点,用于玩家生成
public Vector2 mapMaxSize;//最大地图大小(使其可以在外面设置)
public void GenerateMap()
{
coordsList = new List();
if (mapPoint != null)
{
DestroyImmediate(mapPoint.gameObject);//每帧删除(大概)
mapPoint = new GameObject().transform;
mapPoint.parent = transform;
}
mapCenter = new Coord((int)mapSize.x / 2, (int)mapSize.y / 2);
for (int x = 0; x < mapSize.x; x++)//生成瓦片
{
for (int y = 0;yInstantiate(tilePresf);
newTile.position = new Vector3(-mapSize.x/2+0.5f + x, 0, -mapSize.y/2+y + 0.5f);
newTile.parent = mapPoint;
newTile.localScale *= outinePercent * tilesize;//缩放1在这里!!!-----------------------------------------------------------
coordsList.Add(new Coord(x, y));//把每个瓦片的位置信息传入list用于随机生成障碍物
}
}
int currentOvstacleCount = 0;
coordQueue = new Queue(Utilities.Shuffle(coordsList.ToArray(), seed));//这一步的意义是打乱list里的元素
int obstacleCount = (int)(mapSize.x * mapSize.y * obsPercent);//假设的障碍物数量
Debug.Log(obstacleCount);
bool[,] obstacleMap = new bool[(int)mapSize.x, (int)mapSize.y];//这个布尔是用来记录生成障碍物可否的;
for (int i = 0;i//假设这里可以生成障碍物
Coord tile = GetRandomCoord();//得到一个经过打乱的元素
obstacleMap[tile.x, tile.y] = true;//假设这里不可通行
if(tile != mapCenter && MapIsFullyAccessble(obstacleMap,currentOvstacleCount))
{
Transform newObs = Instantiate(obsPresf);//实例化障碍物
newObs.position = new Vector3(-mapSize.x / 2 + 0.5f + tile.x, 0, -mapSize.y / 2 + tile.y + 0.5f);
newObs.parent = mapPoint;
newObs.localScale *= outinePercent * tilesize;//缩放2在这里!!!-----------------------------------------------------------------------------------------------
newObs.localScale = new Vector3(newObs.localScale.x, 1, newObs.localScale.z);
}
else
{
currentOvstacleCount--;//假设这里可以生成障碍物
obstacleMap[tile.x, tile.y] = false;//假设这里不可通行
}
}
Quad.localScale = new Vector3(mapMaxSize.x, mapMaxSize.y, 1) * tilesize;//缩放3在这里!!!-------------------------------------------------------------------------------------------
}
Coord GetRandomCoord()
{
Coord coord = coordQueue.Dequeue();
coordQueue.Enqueue(coord);
return coord;
}
bool MapIsFullyAccessble(bool[,] obstaqleMap,int currentObstacleCount)
{
bool[,] mapLogs = new bool[obstaqleMap. GetLength(0), obstaqleMap.GetLength(1)];
mapLogs[mapCenter.x, mapCenter.y] = true;//一开始就把中心点标记为已经检测过了
int accessibleTileCount = 1;//可通行区域 +1
Queue queue = new Queue();//用于记录遍历所有的瓦片
queue.Enqueue(new Coord(mapCenter.x, mapCenter.y));
while(queue.Count > 0)
{
Coord coord = queue.Dequeue();
for(int x = -1; x < 2; x++)
{
for (int y = -1; y < 2; y++)
{
int neiighourX = coord.x + x;
int neiighourY = coord.y + y;
if (x == 0 || y == 0)//判断四边
{
if (neiighourX >= 0 && neiighourX < mapSize.x && neiighourY >= 0 && neiighourY < mapSize.y)//判断地图边界,保障障碍物不会超出索引范围
{
if (!mapLogs[neiighourX, neiighourY] && !obstaqleMap[neiighourX, neiighourY])//判断是否已经检测过了
{
queue.Enqueue(new Coord(neiighourX, neiighourY));//加入队列开始下一轮遍历
mapLogs[neiighourX, neiighourY] = true;//标记为已经检测过的
accessibleTileCount++;//可通行区域++
}
}
}
}
}
}
int s = (int)(mapSize.x * mapSize.y) - currentObstacleCount;//得到的实际的可通行区域的数量
return accessibleTileCount == s;//把洪水填充算法得到的可通行区域和实际可通行区域的数量进行比较
}
//private void Start()
//{
//GenerateMap();
//}
}
public struct Coord
{
public int x;//意同下
public int y;//这两个值是用来记录地图的
public Coord(int x,int y)
{
this.x = x;
this.y = y;
}
public static bool operator != (Coord c1,Coord c2)
{
return !(c1 == c2);
}
public static bool operator ==(Coord c1, Coord c2)
{
return c1.x == c2.x && c1.y == c2.y;
}
}
想要改动地图缩放值改动,障碍物大小和障碍物间距一起缩放,还有地板(瓦片)大小与间距,该怎么办?
你可以在缩放的时候,同时调整生成的瓦片和障碍物的位置,以及地图中心点的位置来实现整个地图的缩放。这里有一些实现上的问题需要解决。
首先,你需要在 GenerateMap 函数中,将缩放值 tilesize 的改变作用到瓦片和障碍物的生成上。在你的代码中,你已经在每个瓦片和障碍物生成时使用了 outinePercent * tilesize 来缩放,但是这里的 outinePercent 是控制描边的,不是控制大小的,所以需要改为 tilesize 。
然后,你需要计算出缩放前和缩放后的瓦片和障碍物位置之间的转换关系,以便你可以将它们移动到正确的位置。你可以在生成每个瓦片和障碍物时计算它们在缩放前的位置,然后根据缩放比例将它们移动到缩放后的位置。这样可以确保它们之间的距离保持不变。
最后,你需要计算缩放后的地图大小和中心点的位置。你可以根据缩放比例和地图原始大小来计算缩放后的大小,然后将其应用到地图上。同样,你也需要根据缩放前和缩放后的大小之间的比例来计算新的中心点位置。
这是一个修改后的代码示例:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MapGenerator : MonoBehaviour
{
public float tilesize = 1;
public Transform Quad;
public int seed;
public Transform mapPoint;
public Vector2 mapSize;
public Transform tilePresf;
public Transform obsPresf;
[Range(0, 1)]
public float obsPercent;
List<Coord> coordsList;
[Range(0, 1)]
public float outinePercent;
Queue<Coord> coordQueue;
Coord mapCenter;
public Vector2 mapMaxSize;
public void GenerateMap()
{
coordsList = new List<Coord>();
if (mapPoint != null)
{
DestroyImmediate(mapPoint.gameObject);
mapPoint = new GameObject().transform;
mapPoint.parent = transform;
}
mapCenter = new Coord((int)mapSize.x / 2, (int)mapSize.y / 2);
for (int x = 0; x < mapSize.x; x++)
{
for (int y = 0; y < mapSize.y; y++)
{
Transform newTile = Instantiate(tilePresf);
float newX = (-mapSize.x / 2 + 0.5f + x) * tilesize;
float newY = 0;
float newZ = (-mapSize.y / 2 + y + 0.5f) * tilesize;
newTile.position = new Vector3(newX, newY, newZ);
newTile.localScale *= tilesize;
newTile.parent = mapPoint;
coordsList.Add