【Unity3D】动态路径特效
2023-10-12 本文已影响0人
LittleFatSheep
1 前言
本文通过导航系统(NavMeshAgent)和线段渲染器(LineRenderer)实现了角色走迷宫和绘制路径功能,同时实现动态路径特效。
导航系统的介绍详见博客:导航系统、分离路面导航、动态路障导航。线段渲染器的介绍详见博客:线段渲染器LineRenderer。
动态路径特效的原理是:通过对顶点的 uv 纹理坐标平移实现路径节点的移动效果。
本文完整资源见→Unity3D动态路径特效。
2 烘焙导航网格
1)搭建场景
搭建迷宫场景如下,红的胶囊体是角色。
![](https://img.haomeiwen.com/i20142973/c961ca56f3273236.png)
2)设置导航静态对象
选中地面和所有围墙,将它们设置为 Navigation Static,如下。
![](https://img.haomeiwen.com/i20142973/bced7924b474bd74.png)
3)烘焙导航网格
通过【Window→AI→Navigation】打开导航窗口。
![](https://img.haomeiwen.com/i20142973/45794c1525827c7d.png)
调整参数后,点击 Bake 烘焙导航网格,如下,蓝色的区域是可以行走的区域。
![](https://img.haomeiwen.com/i20142973/f512b3485b5a97cd.png)
3 导航及轨迹绘制
NavController.cs
using UnityEngine;
using UnityEngine.AI;
public class NavController : MonoBehaviour {
private NavMeshAgent navMeshAgent; // 导航网格代理
private LineRenderer lineRenderer; // 线段渲染器
private RaycastHit hit; // 碰撞信息
private NavMeshPath path; // 导航路径
private void Awake() {
AddNavMeshAgent();
AddLineRenderer();
}
private void Update() {
if (Input.GetMouseButtonUp(0) && navMeshAgent.remainingDistance < float.Epsilon) {
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit)) {
if (navMeshAgent.CalculatePath(hit.point, path)) {
DrawLine(path.corners);
navMeshAgent.SetDestination(hit.point);
} else {
lineRenderer.positionCount = 0;
lineRenderer.enabled = false;
}
}
}
}
private void AddNavMeshAgent() { // 添加导航网格代理
navMeshAgent = gameObject.AddComponent<NavMeshAgent>();
navMeshAgent.speed = 100;
navMeshAgent.angularSpeed = 10000;
navMeshAgent.acceleration = 10000;
path = new NavMeshPath();
}
private void AddLineRenderer() { // 添加线段渲染器
lineRenderer = gameObject.AddComponent<LineRenderer>();
lineRenderer.textureMode = LineTextureMode.Tile;
lineRenderer.material = Resources.Load<Material>("PathNodeMat");
lineRenderer.positionCount = 0;
lineRenderer.enabled = false;
}
private void DrawLine(Vector3[] points) { // 绘制顶点
lineRenderer.positionCount = points.Length;
lineRenderer.SetPositions(points);
lineRenderer.enabled = true;
}
}
说明:NavController 脚本组件挂在 Player 角色下。
PathNode.shader
Shader "MyShader/PathNode" { // 路径上的节点移动特效
Properties {
_MainTex("MainTex", 2D) = "white" {} // 节点贴图
_Speed("Speed", Range(0.1, 3)) = 2 // 节点移动速度
_Color("Color", Color) = (1, 1, 1, 1) // 节点颜色
}
SubShader {
tags{"Queue" = "Transparent" "RenderType" = "Transparent" "IgnoreProjector" = "True"}
Blend SrcAlpha OneMinusSrcAlpha // 混合
// Cull off // 双面
Pass {
CGPROGRAM
#include "UnityCG.cginc"
#pragma vertex vert
#pragma fragment frag
sampler2D _MainTex; // 节点贴图
float _Speed; // 节点移动速度
float4 _Color; // 节点颜色
v2f_img vert(appdata_img v) {
v2f_img o;
o.pos = UnityObjectToClipPos(v.vertex); // 模型空间顶点坐标变换到裁剪空间, 等价于: mul(UNITY_MATRIX_MVP, v.vertex)
o.uv = v.texcoord;
o.uv.x -= _Speed * _Time.y; // 通过uv纹理坐标的移动实现节点的移动
return o;
}
fixed4 frag(v2f_img i) : SV_Target {
return tex2D(_MainTex, i.uv) * _Color;
}
ENDCG
}
}
}
说明:在 Assets 目录下面新建 Resources 目录,接着在 Resources 目录下面创建材质,重命名为 PathNodeMat,将 PathNode.shader 与 PathNodeMat 材质绑定,并将路径节点纹理拖拽到 PathNodeMat 的 Main Tex 中。节点纹理如下,它们都是 png 格式,方向朝右,颜色只有灰色和白色(方便在 Shader 中通过 _Color 控制节点颜色)。
![](https://img.haomeiwen.com/i20142973/1d9895499180149a.png)
4 运行效果
1)路径导航效果
![](https://img.haomeiwen.com/i20142973/096b1d594ffa9f57.jpg)
2)飞机路径节点效果
![](https://img.haomeiwen.com/i20142973/e186fcd936bfcc6a.gif)
![](https://img.haomeiwen.com/i20142973/0c3a0a7639f769eb.gif)
3)火箭路径节点效果
![](https://img.haomeiwen.com/i20142973/7ad6023f4fceabd3.gif)
![](https://img.haomeiwen.com/i20142973/fcc73e6204e91762.gif)
4)箭头路径节点效果
![](https://img.haomeiwen.com/i20142973/627b214ad35884b1.gif)
![](https://img.haomeiwen.com/i20142973/69f5fe3fb26b5915.gif)
![](https://img.haomeiwen.com/i20142973/e60f86ee325f9608.gif)
5)其他路径节点效果
![](https://img.haomeiwen.com/i20142973/70f9fa7875b2adbf.gif)
![](https://img.haomeiwen.com/i20142973/4c819f8d596e20cd.gif)
![](https://img.haomeiwen.com/i20142973/e933668c4a24decc.gif)
声明:本文转自【Unity3D】动态路径特效。