效果:
前期准备: 人物能行走在绘制的柏林噪声地图上,是因为用了动态烘焙地图插件
为人物挂载插件中的LocalNavMeshBuilder脚本:
为柏林噪声地图在代码中动态动态动态添加NavMeshSourceTag脚本:
实现:
人物的3种移动:
创建人物,挂载下面脚本即可。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class PlayerMove : MonoBehaviour
{
public ETC m_ETC;
[Header("移动速度")]
public float m_MoveSpeed;
[Header("旋转速度")]
public float m_RotateSpeed;
[Header("小地图箭头")]
public RectTransform arrowImg;
void Update()
{
//小地图箭头指向 与 人物真实方向 保持一致
arrowImg.localEulerAngles = Vector3.back * gameObject.transform.eulerAngles.y;
#region 射线检测移动
if (Input.GetMouseButtonDown(1))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RaycastHit hit))
{
if (hit.collider.CompareTag("PerlinMap"))
{
transform.GetComponent<NavMeshAgent>().SetDestination(hit.point);
}
}
}
#endregion
#region 摇杆移动
float h = m_ETC.GetAxis("Horizontal");
float v = m_ETC.GetAxis("Vertical");
Vector3 dir = new Vector3(h, 0, v);
if (dir!=Vector3.zero)
{
//摇杆结合导航
transform.GetComponent<NavMeshAgent>().SetDestination(dir+transform.position);
//只是摇杆
//transform.LookAt(dir+transform.position);
//transform.Translate(Vector3.forward * Time.deltaTime * 5);
}
#endregion
#region WASD移动
transform.Translate(Vector3.forward*Input.GetAxis("Vertical")*Time.deltaTime*m_MoveSpeed);
transform.Rotate(Vector3.up,Input.GetAxis("Horizontal") * Time.deltaTime * m_RotateSpeed);
#endregion
}
}
绘制柏林地图:
创建一个空对象,挂载下面脚本即可。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 绘制柏林噪声地图
/// </summary>
public class PerlinNoiseMap : MonoBehaviour
{
[Header("噪声强度")]
public float noisily;
[Header("地图长")]
public int mapWidth;
[Header("地图宽")]
public int mapHeight;
[Header("底层颜色")]
public Color downColor;
[Header("上层颜色")]
public Color upColor;
[Header("小地图")]
public Image miniMap;
public GameObject player;
private void Start()
{
VertexHelper vh = new VertexHelper();
Texture2D texture = new Texture2D(mapWidth, mapHeight);
for (int x = 0; x < mapWidth; x++)
{
for (int z = 0; z < mapHeight; z++)
{
float y = Mathf.PerlinNoise(x * noisily * 0.1f, z * noisily * 0.1f);//不乘系数就是平面效果
//uv坐标 最外面一层不算
float uvx = (float)x / (mapWidth - 1);
float uvy = (float)z / (mapHeight - 1);
Color color = Color.Lerp(downColor, upColor, y);
texture.SetPixel(x, z, color);
vh.AddVert(new Vector3(x, y * noisily, z), color, new Vector2(uvx, uvy));
if (x < mapWidth - 1 && z < mapHeight - 1)
{
vh.AddTriangle(x * mapHeight + z, x * mapHeight + z + 1, (x + 1) * mapHeight + z);
vh.AddTriangle((x + 1) * mapHeight + z, x * mapHeight + z + 1, (x + 1) * mapHeight + z + 1);
}
}
}
texture.Apply();
Mesh mesh = new Mesh();
vh.FillMesh(mesh);
gameObject.AddComponent<MeshFilter>().mesh = mesh;
gameObject.AddComponent<MeshCollider>().sharedMesh = mesh;
gameObject.AddComponent<MeshRenderer>().material.mainTexture = texture;
//插件实现,添加NavMeshSourceTag组件,能让玩家在柏林噪声地图上
gameObject.AddComponent<NavMeshSourceTag>();
//小地图材质赋值
Material m = new Material(Shader.Find("UI/Default"));
m.mainTexture = texture;
miniMap.material = m;
}
private void Update()
{
//滚轮控制视野
if (Input.GetAxis("Mouse ScrollWheel") != 0 && transform.localScale.x + Input.GetAxis("Mouse ScrollWheel") >= 1)
{
miniMap.transform.localScale += Vector3.one * Input.GetAxis("Mouse ScrollWheel");
}
else if (Input.GetAxis("Mouse ScrollWheel") != 0 && transform.localScale.x + Input.GetAxis("Mouse ScrollWheel") <= 1)
{
miniMap.transform.localScale += Vector3.one * Input.GetAxis("Mouse ScrollWheel");
}
//重置小地图锚点 以人物为中心
//情况一:人物生成在地图左下角
miniMap.rectTransform.pivot = new Vector2(player.transform.position.x / mapWidth, player.transform.position.z / mapHeight);
//情况二:人物生成在地图中心
//miniMap.rectTransform.pivot = new Vector2((mapWidth / 2 + player.transform.position.x) / mapWidth , (mapHeight / 2 + player.transform.position.z) / mapHeight);
}
}
人物生成在地图左下角(上面代码所述情况一):
人物生成在地图中心(上面代码所述情况二):