Unity—九宫格无限地图(柏林噪声)

1.要有一个柏林噪声的算法,先画出一块地形

[RequireComponent(typeof(MeshRenderer))]
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshCollider))]
public class BoLin : MonoBehaviour
{
    public void Init(Vector2Int pos)
    {
        Mesh mesh = new Mesh();
        VertexHelper vh = new VertexHelper();
        for (int i = 0; i <= PlaneMgr.wh; i++)
        {
            for (int j = 0; j <= PlaneMgr.wh; j++)
            {
                float y = Turbulence((pos.x * PlaneMgr.wh + i), (pos.y * PlaneMgr.wh + j), PlaneMgr.wh);
                float uvx = (float)i / (float)PlaneMgr.wh;
                float uvy = (float)j / (float)PlaneMgr.wh;
                vh.AddVert(new Vector3(i, y * 10, j), Color.white, new Vector2(uvx, uvy));
                if (i != PlaneMgr.wh && j != PlaneMgr.wh)
                {
                    vh.AddTriangle(i * (PlaneMgr.wh + 1) + j, i * (PlaneMgr.wh + 1) + j + 1, (i + 1) * (PlaneMgr.wh + 1) + j);
                    vh.AddTriangle(i * (PlaneMgr.wh + 1) + j + 1, (i + 1) * (PlaneMgr.wh + 1) + j + 1, (i + 1) * (PlaneMgr.wh + 1) + j);
                }
            }
        }
        vh.FillMesh(mesh);
        GetComponent<MeshFilter>().mesh = mesh;
        GetComponent<MeshCollider>().sharedMesh = mesh;
        transform.position = new Vector3(pos.x * PlaneMgr.wh, 0, pos.y * PlaneMgr.wh);
    }
    //调整后的噪声算法(x坐标,y坐标,地图的宽高)
    public static float Turbulence(float x, float z, int wh)
    {
        x = x * 0.03f;
        z = z * 0.03f;
        float y = -0.5f;
        for (int i = 1; i <= (wh + 1) / 12; i *= 2)
        {
            y += Mathf.Abs(Mathf.PerlinNoise(z * i, x * i) / i);
        }
        return y;
    }

2.创建预设挂上噪声脚本

3.创建一个Mgr管理地形的生成

public class PlaneMgr : MonoBehaviour
{
    public Transform player;
    public BoLin panle;
    public static int wh = 100;
    Vector2Int pos = Vector2Int.zero; //人物当前所处地图id
    Dictionary<Vector2Int, BoLin> show = new Dictionary<Vector2Int, BoLin>(); //已经显示出来的数据
    Queue<BoLin> pool = new Queue<BoLin>();  //对象池 存储不适用的物体


    void Start()
    {
        OnMove();
    }
    public void OnMove()
    {
        pos = new Vector2Int((int)(player.position.x - wh / 2) / wh, (int)(player.position.z - wh / 2) / wh);
        //获取周围9块地图
        Dictionary<Rect, Vector2Int> dic = new Dictionary<Rect, Vector2Int>();
        for (int i = -1; i <= 1; i++)
        {
            for (int j = -1; j <= 1; j++)
            {
                Rect rect = new Rect((i + pos.x) * wh, (j + pos.y) * wh, wh, wh);
                dic.Add(rect, new Vector2Int(i + pos.x, j + pos.y));
            }
        }
        Rect playerRect = new Rect(player.position.x - wh / 2, player.position.z - wh / 2, wh * 1.5f, wh * 1.5f);
        //循环到不需要显示的数据
        List<Vector2Int> datas=new List<Vector2Int>();
        foreach (var item in dic)
        {
            if (IsLap(playerRect,item.Key))
            {
                datas.Add(item.Value);
            }
        }
        //找到已经显示但不需要闲的存入对象池
        List<Vector2Int> dustbin=new List<Vector2Int>();    //垃圾箱
        foreach (var item in show)
        {
            if (!datas.Contains(item.Key))
            {
                item.Value.gameObject.SetActive(false);
                pool.Enqueue(item.Value);   //存入对象池
                dustbin.Add(item.Key);  //存入垃圾箱
            }
        }
        //清理垃圾箱
        foreach (var item in dustbin)
        {
            show.Remove(item);
        }
        //创建数据
        foreach (var data in datas)
        {
            //判断数据是否已经显示
            if (!show.ContainsKey(data))
            {
                if (pool.Count>0)
                {
                    show.Add(data,pool.Dequeue());
                    show[data].gameObject.SetActive(true);
                }
                else
                {
                    show.Add(data, Instantiate(panle));
                }
                show[data].Init(data);
            }
        }
    }
    void Update()
    {
        OnMove();
    }
    public bool IsLap(Rect rect1, Rect rect2)
    {
        float rect1MinX = rect1.x - rect1.width / 2;
        float rect1MaxX = rect1.x + rect1.width / 2;
        float rect1MinY = rect1.y - rect1.height / 2;
        float rect1MaxY = rect1.y + rect1.height / 2;

        float rect2MinX = rect2.x - rect2.width / 2;
        float rect2MaxX = rect2.x + rect2.width / 2;
        float rect2MinY = rect2.y - rect2.height / 2;
        float rect2MaxY = rect2.y + rect2.height / 2;

        return rect1MinX < rect2MaxX && rect2MinX < rect1MaxX && rect1MinY < rect2MaxY && rect2MinY < rect1MaxY;
    }
}

4.场景中创建一个空对象挂上Mgr脚本

5.效果

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值