Unity 大地图 高性能路径引导Shader

使用方法

场景内挂新建一个面片 挂上脚本 QuadTillingLine ( 源码在下面 )

需要的时候 挂在玩家脚底下 并设置目标点

挂在玩家脚底下

设置目标位置

csharp 复制代码
var diff = _currentTarget.Pos - m_Pos;
var dir = Mathf.Min( 12, diff.magnitude ) * diff.normalized;
var e = m_Pos + dir;
_lineDriver.SetTarget( e );

源码

C#脚本

csharp 复制代码
using UnityEngine;

[ExecuteAlways]
[RequireComponent( typeof( MeshFilter ), typeof( MeshRenderer ) )]
public class QuadTilingLine : MonoBehaviour
{
    [Header( "Settings" )]
    public Vector3 targetPosition; // 目标点
    public float lineWidth = 0.5f;

    private Transform _t;
    private Renderer _ren;
    private MaterialPropertyBlock _block;
    private MeshFilter _mf;
    private static readonly int LengthId = Shader.PropertyToID( "_TotalLength" );

    private void Awake( )
    {
        Init( );
        GenerateLeftPivotMesh( );
    }

    private void Init( )
    {
        if ( _t == null ) _t = transform;
        if ( _ren == null ) _ren = GetComponent<Renderer>( );
        if ( _mf == null ) _mf = GetComponent<MeshFilter>( );
        if ( _block == null ) _block = new MaterialPropertyBlock( );
    }

    private void OnValidate( )
    {
        Init( );
        if ( _mf.sharedMesh == null || _mf.sharedMesh.name != "LeftPivotQuad" )
        {
            GenerateLeftPivotMesh( );
        }
        UpdateTransform( );
    }
    
    public void SetTarget( Vector3 targetPos )
    {
        targetPosition = targetPos;
        UpdateTransform( );
    }

    private void UpdateTransform( )
    {
        if ( _ren == null ) return;

        //1.计算向量
        Vector3 dir = targetPosition - _t.position;
        float dist = dir.magnitude;

        if ( dist < 0.001f )
        {
            _ren.enabled = false;
            return;
        }
        _ren.enabled = true;

        //2.旋转: Z轴指向目标
        float angle = Mathf.Atan2( dir.y, dir.x ) * Mathf.Rad2Deg;
        _t.rotation = Quaternion.Euler( 0, 0, angle );

        //3.缩放: X轴变长
        //因为mesh轴心在左边,所以它只向右长,不用修位置
        _t.localScale = new Vector3( dist, lineWidth, 1f );

        //4.set shader属性
        _ren.GetPropertyBlock( _block );
        _block.SetFloat( LengthId, dist );
        _ren.SetPropertyBlock( _block );
    }

    //生成左轴心Mesh挽歌
    private void GenerateLeftPivotMesh( )
    {
        Mesh mesh = new Mesh( );
        mesh.name = "LeftPivotQuad";

        //顶点:X从0到1 Y从-0.5到0.5
        Vector3[] vertices = new Vector3[]
        {
            new Vector3(0, -0.5f, 0),
            new Vector3(1, -0.5f, 0),
            new Vector3(0, 0.5f, 0),
            new Vector3(1, 0.5f, 0)
        };

        //UV
        Vector2[] uv = new Vector2[]
        {
            new Vector2(0, 0),
            new Vector2(1, 0),
            new Vector2(0, 1),
            new Vector2(1, 1)
        };

        //三角形索引
        int[] triangles = new int[] { 0, 2, 1, 2, 3, 1 };

        mesh.vertices = vertices;
        mesh.uv = uv;
        mesh.triangles = triangles;
        mesh.RecalculateBounds( );

        _mf.mesh = mesh;
    }
}

Shader脚本

c 复制代码
Shader "Unlit/QuadTilingLine"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Color ("Color", Color) = (1,1,1,1)
        _Density ("Density", Float) = 1.0 
        _ScrollSpeed ("Scroll Speed", Float) = -1.0
    }
    SubShader
    {
        Tags { "Queue"="Transparent" "RenderType"="Transparent" }
        Blend SrcAlpha OneMinusSrcAlpha
        ZWrite Off
        Cull Off

        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;
            float4 _Color;
            float _Density;
            float _TotalLength;
            float _ScrollSpeed;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                float2 uv = TRANSFORM_TEX(v.uv, _MainTex);

                uv.x *= _TotalLength * _Density;
                uv.x += _Time.y * _ScrollSpeed;
                
                o.uv = uv;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                return tex2D(_MainTex, i.uv) * _Color;
            }
            ENDCG
        }
    }
}

原理

我们不需要真的从地图中心点拉一个 几百米甚至更长的引导路线到目标点, 我们需要通过目标点和自身位置计算一个超出屏幕的向量即可

引导路线如果只是固定的一条线 容易被忽略 所以我们需要让他动起来

在shader里只需要一句简单的滚uv就能让一张图片跑马灯

uv.x += _Time.y * _ScrollSpeed;

相关推荐
RReality16 小时前
【Unity Shader URP】序列帧动画(Sprite Sheet)实战教程
unity·游戏引擎
mxwin16 小时前
Unity URP 多线程渲染:理解 Shader 变体对加载时间的影响
unity·游戏引擎·shader
呆呆敲代码的小Y18 小时前
【Unity工具篇】| 游戏完整资源热更新流程,YooAsset官方示例项目
人工智能·游戏·unity·游戏引擎·热更新·yooasset·免费游戏
nainaire18 小时前
自学虚幻引擎记录1
游戏引擎·虚幻
想你依然心痛21 小时前
HarmonyOS 5.0游戏开发实战:构建高性能2D休闲游戏引擎与 monetization 系统
华为·游戏引擎·harmonyos
黄思搏2 天前
基于标注平台数据的 Unity UI 自动化构建工作流设计与工程实践
ui·unity·蓝湖·vectoui
羊羊20352 天前
开发手札:Unity6000与Android交互
android·unity·android-studio
Zarek枫煜3 天前
C3 编程语言 - 现代 C 的进化之选
c语言·开发语言·青少年编程·rust·游戏引擎
Sator13 天前
Unity AStarPath的踩坑点
unity
榮華3 天前
DOTA全图透视辅助下载DOTA全图科技辅助下载DOTA外挂下载魔兽争霸WAR3全图下载
数据库·科技·游戏·游戏引擎·游戏程序·ai编程·腾讯云ai代码助手