本文主要是介绍Unity3D中物体移动拖影,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
两个脚本即可实现
脚本一:获取对象下的skinMeshRenderer或者meshRenderer组件
using UnityEngine;
using System.Collections;
using System.Collections.Generic;namespace DragonRun
{[ExecuteInEditMode]public class PlayerShadow : MonoBehaviour{public Shader curShader;private List<Vector3> offsets = new List<Vector3>(); // 存储前几帧的坐标private List<Material> mats = new List<Material>(); // 存储人物的材质,用于给shader传参数// Use this for initializationvoid Start(){offsets.Add(transform.position);offsets.Add(transform.position);offsets.Add(transform.position);offsets.Add(transform.position);var skinMeshRenderer = gameObject.GetComponentsInChildren<SkinnedMeshRenderer>();foreach (var mr in skinMeshRenderer)mats.Add(mr.material);var meshRenderer = gameObject.GetComponentsInChildren<MeshRenderer>();foreach (var mr in meshRenderer)mats.Add(mr.material);foreach (var mat in mats)mat.shader = curShader;}private int frame = 3;// Update is called once per framevoid Update(){this.frame--;if (this.frame <= 0){foreach (var mat in mats) // 每帧将之前的位置传入shader中{mat.SetVector("_Offset0", offsets[3] - transform.position);mat.SetVector("_Offset1", offsets[2] - transform.position);mat.SetVector("_Offset2", offsets[1] - transform.position);mat.SetVector("_Offset3", offsets[0] - transform.position);}offsets.Add(transform.position);offsets.RemoveAt(0);this.frame = 99;//此处修改控制残影显示的间隔}}}
}
脚本二:构建标准Shader脚本,根据上面脚本中记录的帧信息进行残影显示
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'Shader "Custom/Ghost" {Properties{_MainTex("Main Tex", 2D) = "white" {}_Offset0("Offset 0", vector) = (0, 0, 0, 0) // 这里只显示4个残影,所以传入4个偏移值_Offset1("Offset 1", vector) = (0, 0, 0, 0)_Offset2("Offset 2", vector) = (0, 0, 0, 0)_Offset3("Offset 3", vector) = (0, 0, 0, 0)}CGINCLUDE
#include "UnityCG.cginc"sampler2D _MainTex;float4 _Offset0;float4 _Offset1;float4 _Offset2;float4 _Offset3;struct v2f {float4 pos : POSITION;float2 uv : TEXCOORD0;};v2f vert_normal(appdata_base v) {v2f o;o.pos = UnityObjectToClipPos(v.vertex);o.uv = v.texcoord;return o;}v2f vert_offset_1(appdata_base v) {v2f o;float4 pos = mul(unity_ObjectToWorld, v.vertex);o.pos = mul(UNITY_MATRIX_VP, pos + _Offset0);o.uv = v.texcoord;return o;}v2f vert_offset_2(appdata_base v) {v2f o;float4 pos = mul(unity_ObjectToWorld, v.vertex);o.pos = mul(UNITY_MATRIX_VP, pos + _Offset1);o.uv = v.texcoord;return o;}v2f vert_offset_3(appdata_base v) {v2f o;float4 pos = mul(unity_ObjectToWorld, v.vertex);o.pos = mul(UNITY_MATRIX_VP, pos + _Offset2);o.uv = v.texcoord;return o;}v2f vert_offset_4(appdata_base v) {v2f o;float4 pos = mul(unity_ObjectToWorld, v.vertex);o.pos = mul(UNITY_MATRIX_VP, pos + _Offset3);o.uv = v.texcoord;return o;}float4 frag_normal(v2f i) : COLOR{return tex2D(_MainTex, i.uv);}float4 frag_color(v2f i) : COLOR{ // 将残影的alpha值设为0.5float4 c;c = tex2D(_MainTex, i.uv);c.w = 0.5;return c;}ENDCGSubShader { // 这里用4个pass来渲染残影,第5个pass渲染自身Pass{ // 从最远的开始渲染ZWrite OffBlend SrcAlpha OneMinusSrcAlphaCGPROGRAM#pragma vertex vert_offset_4#pragma fragment frag_colorENDCG}Pass{ZWrite OffBlend SrcAlpha OneMinusSrcAlphaCGPROGRAM#pragma vertex vert_offset_3#pragma fragment frag_colorENDCG}Pass{ZWrite OffBlend SrcAlpha OneMinusSrcAlphaCGPROGRAM#pragma vertex vert_offset_2#pragma fragment frag_colorENDCG}Pass{ZWrite OffBlend SrcAlpha OneMinusSrcAlphaCGPROGRAM#pragma vertex vert_offset_1#pragma fragment frag_colorENDCG}Pass{ // 渲染自身,这时要开启 ZWriteBlend SrcAlpha OneMinusSrcAlphaCGPROGRAM#pragma vertex vert_normal#pragma fragment frag_normalENDCG}}FallBack "Diffuse"
}
最后,将PlayerShadow脚本挂在物体上,并将shader脚本赋值给Cur Shader变量,运行如下图所示:
注意:加上脚本后,未运行状态下,鼠标拖动物体也会产生拖影,因为存储了帧数据,并没有删除,只能迭代。
这篇关于Unity3D中物体移动拖影的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!