Unity 导航路线生成,小地图同步映射, 经过以后地图与小地图删除点位(点击小地图控制导航以及点击场景导航都会有路径点和路径点图标)

效果:(如下图所示)

操作方法:

搭建小地图UI

截取图片

创建地面

挂载如下代码:

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

[RequireComponent(typeof(MeshFilter), typeof(MeshCollider), typeof(MeshRenderer))]
public class Map : MonoBehaviour
{
    //宽高
    [SerializeField] private int w, h;
    //颜色1和颜色2,用于设置渐变
    [SerializeField] private Color color1, color2;
    //存储水面上面的顶点的集合
    public List<Vector3> verticesPositions;
    //纹理
    private Texture2D _texture;
    //顶点辅助器
    private VertexHelper vh;
    //mesh网格
    private Mesh _mesh;

    // Start is called before the first frame update
    void Start()
    {
        verticesPositions= new List<Vector3>();
        _texture = new(w + 1, h + 1);
        vh = new();
        _mesh = new();
        //循环宽高
        for (int i = 0; i <= w; i++)
        {
            for (int j = 0; j <= h; j++)
            {
                //柏林噪声获取高度
                float y = Mathf.PerlinNoise(i * 0.2f, j * 0.2f);
                //uv坐标
                float uvx = (float)i / w;
                float uvy = (float)j / h;
                //添加顶点
                vh.AddVert(new(i, y * 5, j), Color.white, new(uvx, uvy));

                //设置纹理颜色
                _texture.SetPixel(i, j, Color.Lerp(color1, color2, y));
                //绘制三角
                if (i < w && j < h && y * 5 > 1.3f)
                {
                    vh.AddTriangle(j + i * (h + 1), j + 1 + i * (h + 1), j + 1 + 1 + h + i * (h + 1));
                    vh.AddTriangle(j + i * (h + 1), j + 1 + 1 + h + i * (h + 1), j + 1 + h + i * (h + 1));
                }
            }
        }
        //顶点辅助器给mesh网格赋值
        vh.FillMesh(_mesh);
        //mesh赋值给网格过滤器
        GetComponent<MeshFilter>().mesh = _mesh;
        //新建材质球
        Material material = new(Shader.Find("Standard"))
        {
            mainTexture = _texture
        };
        //网格渲染器赋值材质球
        GetComponent<MeshRenderer>().material = material;
        //网格碰撞器赋值mesh网格
        GetComponent<MeshCollider>().sharedMesh = _mesh;
        //加载水面
        Instantiate(Resources.Load<GameObject>("Water"));
        //设置纹理打包模式
        _texture.wrapMode = TextureWrapMode.Clamp;
        //应用纹理更改
        _texture.Apply();
    }
    // Update is called once per frame
    void Update()
    {
    }
}

小地图挂载

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

//Image有Mask,两个Image子类,一个挂脚本,一个作为中心点
public class SmallMap : MonoBehaviour, IPointerClickHandler
{
    //创建地图脚本的引用,用来获取其中的装饰物集合
    public NavMeshManager navMesh;
    //玩家
    public Transform player;
    //地图的rectTransform
    public RectTransform _rectTransform, Startpoint;
    //玩家的对象
    public NavMeshAgent nav;
    //控制缩放的Slider
    public Slider Slider;
    //存储路径点的图片的集合
    public List<GameObject> imageList = new List<GameObject>();

    private void Awake()
    {
        Slider.value = 1;
        _rectTransform = GetComponent<RectTransform>();
    }
    private void Update()
    {
        //实时获取大地图的比例(100是柏林噪声地图的宽高)
        float x = nav.transform.position.x / 100;
        float y = nav.transform.position.z / 100;
        //中心点跟随移动
        _rectTransform.pivot = new Vector2(x, y);
        //滑动条控制缩放
        //_rectTransform.localScale = Vector3.one * Slider.value;
        //滚轮控制缩放
        if (Input.GetAxis("Mouse ScrollWheel") != 0)
        {
            _rectTransform.localScale += Vector3.one * Input.GetAxis("Mouse ScrollWheel")*2;
            //设置最小缩放限制
            if (_rectTransform.localScale.x <= 0.75f)
            {
                _rectTransform.localScale = new Vector3(0.75f, 0.75f, 0.75f);
            }
        }
    }
    //创建路径点Image
    public void CreateImage()
    {
        //生成地图装饰物
        for (int i = 0; i < navMesh.spawnedCubes.Count; i++)
        {
            GameObject bodyimg = GameObject.Instantiate(Resources.Load<GameObject>("bodyimg"), transform);
            if (navMesh.spawnedCubes[i].tag == "Cube")
            {
                bodyimg.GetComponent<Image>().color = Color.yellow;
            }
            //都加起始位置,就是小地图 的左下角的位置(因为小地图一直在移动,所以用这个空对象作为起点)
            float a = navMesh.spawnedCubes[i].transform.position.x / 100 * _rectTransform.sizeDelta.x + Startpoint.localPosition.x;
            float b = navMesh.spawnedCubes[i].transform.position.z / 100 * _rectTransform.sizeDelta.y + Startpoint.localPosition.y;
            bodyimg.transform.localPosition = new Vector2(a, b);
            imageList.Add(bodyimg);
        }
    }
    //删除路径点Image
    public void DeletImage()
    {
        for (int i = 0; i < imageList.Count; i++)
        {
            Destroy(imageList[i].gameObject);
        }
        imageList.Clear();  
    }
    public void OnPointerClick(PointerEventData eventData)
    {
        //mapImage 的标签
        if (eventData.pointerPressRaycast.gameObject.tag == "Map")
        {
            var isClick =
            RectTransformUtility.ScreenPointToLocalPointInRectangle(_rectTransform, eventData.position, null,
                out var point);
            float x = point.x / _rectTransform.sizeDelta.x * 100;
            float y = point.y / _rectTransform.sizeDelta.y * 100;
            var endpos = player.position + new Vector3(x, 0, y);
            nav.SetDestination(endpos);
            //点击小地图控制人物移动
            navMesh.isGeneratingCubes = true;
        }
    }
}

角色挂载

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class NavMeshManager : MonoBehaviour
{
    public SmallMap map;
    public NavMeshAgent agent; // 角色的 NavMeshAgent
    public GameObject cubePrefab; // 用于生成的 Cube 预制件
    public float cubeSpacing = 2f; // Cube 之间的距离

    public List<GameObject> spawnedCubes = new List<GameObject>();
    public bool isGeneratingCubes = false;
    void Update()
    {
        //有这个可以点击地图移动,让小地图动
        //if (Input.GetMouseButtonDown(0))
        //{
        //    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        //    if (Physics.Raycast(ray, out RaycastHit hit))
        //    {
        //        // 设置导航目标点
        //        agent.SetDestination(hit.point);
        //        isGeneratingCubes = true;
        //    }
        //}

        if (isGeneratingCubes && agent.hasPath && agent.remainingDistance > agent.stoppingDistance)
        {
            // 清除之前生成的所有 Cube
            ClearCubes();
            // 生成路径上的 Cube
            GenerateCubesAlongPath(agent.path);
            
            isGeneratingCubes = false;
        }
    }

    private void GenerateCubesAlongPath(NavMeshPath path)
    {
        if (path.corners.Length < 2)
        {
            return;
        }

        Vector3 previousCorner = path.corners[0];
        float distanceSinceLastCube = 0f;

        for (int i = 1; i < path.corners.Length; i++)
        {
            Vector3 corner = path.corners[i];
            float segmentLength = Vector3.Distance(previousCorner, corner);

            while (distanceSinceLastCube < segmentLength)
            {
                Vector3 direction = (corner - previousCorner).normalized;
                Vector3 cubePosition = previousCorner + direction * distanceSinceLastCube;

                GameObject cube = Instantiate(cubePrefab, cubePosition, Quaternion.identity);
                spawnedCubes.Add(cube);

                distanceSinceLastCube += cubeSpacing;
            }
            
            distanceSinceLastCube -= segmentLength;
            previousCorner = corner;
        }
    }
    //清除生成的代表路径点的Cube
    private void ClearCubes()
    {
        foreach (var cube in spawnedCubes)
        {
            Destroy(cube);
        }
        spawnedCubes.Clear();
    }

    private void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.CompareTag("Cube"))
        {
            //碰撞就刷新
            map.DeletImage();
            Destroy(other.gameObject);
            spawnedCubes.Remove(other.gameObject);
            map.CreateImage();
        }
    }
}

预制体预览

路径点Image

路径点预制体

角色预制体

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值