用Line Renderer和简单的uv动画Shader实现一个01数据流传输的效果,大致效果如图

GIF_20220425_111238

步骤:

制作01纹理素材->编写shader->制作Line Renderer预制件->用脚本设置Line Renderer的节点位置

纹理素材

image-20220425113401844

做一个大概这种感觉的透明背景图片就行,注意中间的间距和两边加起来的间距差不多,使得纹理位移时(边上的间距会连接起来)间距基本看着相同

白色可以方便后期在shader中调色

shader

只需要处理片元部分,在x方向上按时间移动uv值就可以(_Time*运动速度)

考虑到数据运动过于流畅,尝试通过floor函数离散化速度增量,实现数据跳跃性运动的效果(当然也可以不加)

Shader "Custom/DynamicDottedLineShader"
{
	Properties
	{
		_Color ("Color", Color) = (1, 1, 1, 1)
        // 运动速度
		_Speed("Speed", Float) = 1.0
		_MainTex("MainTex", 2D) = "white" {}
        // 离散化步长,0.1代表uv运动一轮将包含10帧,1则整个图片会静止不动
        // 不需要间断运动效果可以去掉
		_Discrete ("Discrete", Range(0.01,1)) = 0.1
	}
SubShader
{
    // 透明效果默认相关设置
	Tags{ "RenderType" = "Transparent"  "Queue" = "Transparent" "IgnoreProjector" = "True" }
	Pass {
		Tags { "LightMode"="ForwardBase" }

        // 透明效果默认相关设置
		ZWrite Off
		Blend SrcAlpha OneMinusSrcAlpha

		CGPROGRAM

		#pragma vertex vert  
		#pragma fragment frag
		
		#include "UnityCG.cginc"

		fixed4 _Color;
		float _Speed;
		sampler2D _MainTex;
		float4 _MainTex_ST;
		float _Discrete;

		struct a2v {  
		    float4 vertex : POSITION; 
		    float2 texcoord : TEXCOORD0;
		};  
		
		struct v2f {  
		    float4 pos : SV_POSITION;
		    float2 uv : TEXCOORD0;
		};  

        // 顶点函数无需修改
		v2f vert (a2v v) {
			v2f o;
			o.pos = UnityObjectToClipPos(v.vertex);
			o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
			return o;
		}

		fixed4 frag(v2f i) : SV_Target {
            // 偏移值为时间*速度
			float delta = _Time.y * _Speed;
            // 如果不需要间断运动效果可去掉这两行
            // delta按_Discrete扩大,floor离散化后再缩小
			delta = floor(delta / _Discrete);
			delta = delta * _Discrete;
            // 只在x方向移动uv
            // 由于后续纹理会被设为Tile(堆叠),所以不需要控制uv在(0,1)内
			half2 uv = i.uv + half2(delta, 0);
			fixed4 c = tex2D(_MainTex, uv);
			c.rgb *= _Color;
			return c;
		}	
	ENDCG
	}
}
Fallback "Diffuse"
}

LineRenderer

新建一个空物体并加上LineRenderer组件,并将TextureMode设置为Tile(实现图案重复),Cast Shadows设为Off,其他保持默认设置即可,如图所示:

image-20220425141933819

可以试着设置该组件节点(position)数为2,可以发现已经实现了数据流动效果,但是试着再添加多个点时,会发现纹理会被扭曲,所以要连接多个物体需要建立多个Line Renderer组件,每个组件仅包含两个position

现在先该物体拖到资产页中保存为prefab,便于编写脚本动态

编写脚本连接并跟随物体

在初始化中连接物体:

public class LineDrawer : MonoBehaviour
{
    // 需要连接的物体位置列表
    public Transform[] connectObjectsPos;
    public List<LineRenderer> lines;
	void Start()
    {
        for (int i = 0; i < connectObjectsPos.Length; i++ )
        {
            // 物体少于等于1个不连接
            if (connectObjectsPos.Length <= 1)
                break;
            // 物体少于2个时只连接一根
            if (connectObjectsPos.Length == 2 && i == 1) {
                continue;
            }
            int p1 = i, p2 = (i + 1) % connectObjectsPos.Length;
            Vector3 pos1 = connectObjectsPos[p1].position;
            Vector3 pos2 = connectObjectsPos[p2].position;
            LineRenderer line = Instantiate(linePrefab).GetComponent<LineRenderer>();
            // 保存该组件,便于后续做跟随
            lines.Add(line);
            line.positionCount = 2;
            line.SetPosition(0, pos1);
            line.SetPosition(1, pos2);
        }
    }
}

这种方式可以实现n个物体的首尾连接(这样n个物体需要n个lineRenderer组件),如果需要连接方式可按情况修改

需要跟随的场合,同样只需要在Update中循环connectObjectsPos,赋值新的位置给每个line的2个position即可