Unity Mesh地形和小地图的绘制

众所周知,小地图的制作在游戏里面的应用是非常广泛的,通过小地图我们可以实时获取玩家在世界场景中的信息,给玩家更好的体验。在unity中,我们可以通过新建相机,设置相机的正交模式和位置,深度等可以实现简易的小地图效果;也可以通过RawImage实现,但是会影响性能。这里我将介绍另外一种:创建图片,给图片贴图,实现和地形同步的小地图。

主要运用了Mesh和Texture2D。

首先,我们需要创建一个空对象(命名为Map),为了挂载生成地形的脚本。再创建一个UI Image图片作为我们的小地图图片(命名为miniMap)。

将DrawMap脚本挂载到Map上

这里也是可以手动调整颜色值的。

绘制地形的脚本:DrawMap

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
public class DrawMap : MonoBehaviour
{
    //地形长,宽
    [Range(0,250)]
    public int len , wide ;
    //网格
    Mesh mesh;
    //顶点辅助器
    VertexHelper vh;
    //纹理
    Texture2D texture;
    //颜色
    [SerializeField] Color color1, color2;
    private void Awake()
    {
        //根据尺寸创建地形
        CreateMap(len,wide);
    }
    /// <summary>
    /// 创建地形
    /// </summary>
    /// <param name="len">长</param>
    /// <param name="wide">宽</param>
    private void CreateMap(int len,int wide)
    {
        mesh = new Mesh();
        vh = new VertexHelper();
        texture = new Texture2D(len, wide);
        for (int i = 0; i < len; i++)
        {
            for (int j = 0; j < wide; j++)
            {
                //通过柏林噪声计算地形的高度值(y值)
                float y = Mathf.PerlinNoise(i * 0.04f, j * 0.04f) * 10;
                //添加顶点并计算对应的uv坐标
                vh.AddVert(new Vector3(i, y, j), Color.white, new Vector2(i / (len * 1.0f), j / (wide * 1.0f)));         
                //根据高度判断是否为水面 给纹理渲染不同的颜色
                if (y > 4f)
                {
                    texture.SetPixel(i, j, color2);
                }
                else
                {
                    texture.SetPixel(i, j, color1);
                }
                //计算顶点下标连接路线
                if (i < len - 1 && j < wide - 1)
                {
                    vh.AddTriangle(i * wide + j, (i + 1) * wide + j + 1, (i + 1) * wide + j);
                    vh.AddTriangle(i * wide + j, i * wide + j + 1, (i + 1) * wide + j + 1);
                }
            }
        }
        //应用纹理
        texture.Apply();
        //绘制网格
        vh.FillMesh(mesh);
        GetComponent<MeshFilter>().mesh = mesh;
        //给网格附上纹理
        Material mat = new Material(Shader.Find("Standard"));
        mat.mainTexture = texture;
        GetComponent<MeshRenderer>().material = mat;
    }
}

因为我们知道,Mesh网格绘制的顶点数不能超过65000个,所以这里我将地形的长宽做了一个限制,避免可能出现的报错。

然后通过Mathf类的柏林噪声方法(Mathf.PerlinNoise())计算出地形的高度值Y。这个Y值就是我们绘制地形,给地形贴纹理的依据,给小地图贴图的关键。因为一般游戏中都是根据地形的高度来分配相关的地貌的如山体、平地、河流等等。这里我们只设置简单的两种类型:地面和水面(河流)。

根据上面计算出来Y值判断,如果Y值大于4就说明是地面,否则就判定为水面。根据这个逻辑计算纹理的颜色分配,最后绘制地形网格,给定纹理,就可以生成地形了。

地形完成后,我们就要给小地图(miniMap)挂上MiniMap脚本,并手动将map拖到小地图脚本组件中。

小地图的脚本:MiniMap

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class MiniMap : MonoBehaviour
{
    [SerializeField]
    Texture2D texture;
    [SerializeField]
    DrawMap map;
 
    void Start()
    {
        texture = new Texture2D(1024, 1024);
        //获取地形的顶点数组
        Vector3[] verties = map.gameObject.GetComponent<MeshFilter>().mesh.vertices;
        int len = map.len;
        int wide = map.wide;

        for (int x = 0; x < len; x++)
        {
            for (int z = 0; z < wide; z++)
            {
                //计算小地图的纹理
                float y = verties[x*wide+z].y;
                if(y>4f)
                {
                    texture.SetPixel(x, z, Color.green);
                }
                else
                {
                    texture.SetPixel(x, z, Color.blue);
                }
            }
        }
        //将上面的纹理应用
        texture.Apply();
       //创建新的精灵图给图片赋值
        GetComponent<Image>().sprite = Sprite.Create(texture, new Rect(0, 0, wide, len), new Vector2(0.5f, 0.5f));     
    }

    void Update()
    {
        
    }
}

这里通过获取绘制地形脚本中的mesh顶点数据,这样我们也就知道了Y值,同样也是根据这个Y值,来计算我们小地图的Texture2D贴图纹理。通过Sprite.Create()创建新的精灵图给我们的小地图图片赋值。

这样我们的最终效果就实现了。

最终效果:

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值