无限地图顾名思义就是永远也到达不了终点的地图。但并不意味着要不停的加载生成地图。
可以通过算法实现分块加载地图,并改变地图的位置来实现无限地图。
首先在场景中创建一个空对象。挂上此脚本。
Player是主角,playerwh和terrainwh是玩家和地图的检查范围,prefab是地图预制体。
代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TerrainMgr : MonoBehaviour
{
public GameObject player;
public float playerWH;
public float TerrainWH;
public GameObject prefab;
Vector3 playerpos;
GameObject terrain;
Dictionary<Vector2, GameObject> showDic = new Dictionary<Vector2, GameObject>();
//对象池
Queue<GameObject> pool = new Queue<GameObject>();
void Start()
{
playerpos = player.transform.position;
player.transform.position = new Vector3(0.1f, 0, 0);
}
// Update is called once per frame
void Update()
{
if (playerpos != player.transform.position)
{
List<Vector2> showlist = new List<Vector2>();
Rect playerRect = new Rect(player.transform.position.x, player.transform.position.z, playerWH, playerWH);
int x = (int)(player.transform.position.x / TerrainWH);
int z = (int)(player.transform.position.z / TerrainWH);
showlist.Add(new Vector2(x, z));
if (IsLap(playerRect, new Rect((x + 1) * TerrainWH, z * TerrainWH, TerrainWH, TerrainWH)))
{
showlist.Add(new Vector2(x + 1, z));
}
if (IsLap(playerRect, new Rect((x - 1) * TerrainWH, z * TerrainWH, TerrainWH, TerrainWH)))
{
showlist.Add(new Vector2(x - 1, z));
}
if (IsLap(playerRect, new Rect(x * TerrainWH, (z + 1) * TerrainWH, TerrainWH, TerrainWH)))
{
showlist.Add(new Vector2(x, z + 1));
}
if (IsLap(playerRect, new Rect(x * TerrainWH, (z - 1) * TerrainWH, TerrainWH, TerrainWH)))
{
showlist.Add(new Vector2(x, z - 1));
}
if (IsLap(playerRect, new Rect((x + 1) * TerrainWH, (z + 1) * TerrainWH, TerrainWH, TerrainWH)))
{
showlist.Add(new Vector2(x + 1, z + 1));
}
if (IsLap(playerRect, new Rect((x - 1) * TerrainWH, (z + 1) * TerrainWH, TerrainWH, TerrainWH)))
{
showlist.Add(new Vector2(x - 1, z + 1));
}
if (IsLap(playerRect, new Rect((x + 1) * TerrainWH, (z - 1) * TerrainWH, TerrainWH, TerrainWH)))
{
showlist.Add(new Vector2(x + 1, z - 1));
}
if (IsLap(playerRect, new Rect((x - 1) * TerrainWH, (z - 1) * TerrainWH, TerrainWH, TerrainWH)))
{
showlist.Add(new Vector2(x - 1, z - 1));
}
List<Vector2> deslist = new List<Vector2>();
foreach (var item in showDic.Keys)
{
if (!showlist.Contains(item))
{
showDic[item].SetActive(false);
pool.Enqueue(showDic[item]);
deslist.Add(item);
}
}
foreach (var item in deslist)
{
showDic.Remove(item);
}
foreach (var item in showlist)
{
if (!showDic.ContainsKey(item))
{
if (pool.Count>0)
{
terrain = pool.Dequeue();
terrain.SetActive(true);
}
else
{
terrain = Instantiate(prefab);
}
terrain.transform.position = new Vector3(item.x * TerrainWH, 0, item.y * TerrainWH);
showDic.Add(item, terrain);
}
}
playerpos = player.transform.position;
}
}
public bool IsLap(Rect a, Rect b)
{
float aMinX = a.x - a.width / 2;
float aMaxX = a.x + a.width / 2;
float aMinZ = a.y - a.height / 2;
float aMaxZ = a.y + a.height / 2;
float bMinX = b.x - b.width / 2;
float bMaxX = b.x + b.width / 2;
float bMinZ = b.y - b.height / 2;
float bMaxZ = b.y + b.height / 2;
if (aMinX < bMaxX &&
bMinX < aMaxX &&
aMinZ < bMaxZ &&
bMinZ < aMaxZ
)
{
return true;
}
else
{
return false;
}
}
}