一、路径指向箭头
1、创建shader
//导航箭头 Shader "Custom/NavPathArrow" { Properties { _MainTex ("Texture", 2D) = "white" {} _ScrollYSpeed("Y Scroll Speed", Range(-20, 20)) = 2 } SubShader { Tags { "Queue" = "Transparent" "RenderType"="Transparent" } LOD 100 //双面渲染 Cull Off //Alpha混合 Blend SrcAlpha OneMinusSrcAlpha Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; fixed _ScrollYSpeed; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } fixed4 frag(v2f i) : SV_Target { fixed2 uv = i.uv; uv.y += _ScrollYSpeed * _Time; fixed4 col = tex2D(_MainTex, uv); return col; } ENDCG } } }
2、创建材质
3、创建脚本
using System.Collections; using System.Collections.Generic; using UnityEngine; /// <summary> /// 导航箭头 /// </summary> public class NavPathArrow : MonoBehaviour { //箭头3D对象Quad,贴图为一张向上的箭头 [SerializeField] private MeshRenderer meshRenderer; [SerializeField] private List<Transform> points = new List<Transform>(); private List<MeshRenderer> lines = new List<MeshRenderer>(); private float xscale = 1f; private float yscale = 1f; private void Awake() { //箭头宽度缩放值 xscale = meshRenderer.transform.localScale.x; //箭头长度缩放值 yscale = meshRenderer.transform.localScale.y; meshRenderer.gameObject.SetActive(false); } void Start() { DrawPath(); } public void SetScale(float xscale, float yscale) { this.xscale = xscale; this.yscale = yscale; } public void DrawPath() { if (points == null || points.Count <= 1) return; for (int i=0; i< points.Count-1; i++) { DrawLine(points[i].position, points[i+1].position, i); } } public void DrawPath(Vector3[] points) { if (points == null || points.Length <= 1) return; for (int i = 0; i < points.Length - 1; i++) { DrawLine(points[i], points[i + 1], i); } } public void HidePath() { for (int i = 0; i < lines.Count; i++) lines[i].gameObject.SetActive(false); } private void DrawLine(Vector3 start, Vector3 end, int index) { MeshRenderer mr; if (index >= lines.Count) { mr = Instantiate<MeshRenderer>(meshRenderer); lines.Add(mr); } else { mr = lines[index]; } var tran = mr.transform; var length = Vector3.Distance(start, end); tran.localScale = new Vector3(xscale, length, 1); tran.position = (start + end) / 2; //指向end tran.LookAt(end); //旋转偏移 tran.Rotate(90, 0, 0); mr.material.mainTextureScale = new Vector2(1, length * yscale); mr.gameObject.SetActive(true); } }
4、使用
效果
二、目标指向箭头
NavTargetArrow.shader
//目标箭头 Shader "Custom/NavTargetArrow" { Properties { _MainTex("Texture", 2D) = "white" {} } SubShader { Tags { "LightMode" = "ForwardBase" "Queue" = "Overlay" "RenderType" = "Overlay" } LOD 100 //关闭深度测试,让箭头总显示在其他模型之上 ZTest Off //双面渲染 Cull Off //Alpha混合 Blend SrcAlpha OneMinusSrcAlpha Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; v2f vert(appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } fixed4 frag(v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.uv); return col; } ENDCG } } }
NavTargetArrow.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; /// <summary> /// 目标箭头 /// 由Quad和1张向上的箭头纹理实现 /// </summary> public class NavTargetArrow : MonoBehaviour { public Vector3 target; public float radius=1f; private MeshRenderer meshRenderer; private Transform mTransform; private Vector3 mLocalPosition; private bool hide = false; private void Awake() { mTransform = transform; mLocalPosition = mTransform.localPosition; meshRenderer = GetComponent<MeshRenderer>(); } void Update() { hide = Vector3.Distance(target, mTransform.position) < radius; meshRenderer.enabled = !hide; if (hide) return; target.y = mTransform.position.y; mTransform.LookAt(target); //旋转偏移 mTransform.Rotate(90, 0, 0); //将箭头往指向方向前移一点 var direction = target - mTransform.position; direction = mTransform.parent.InverseTransformDirection(direction); direction = direction.normalized; direction.y = mLocalPosition.y; mTransform.localPosition = direction; } }