Unity3D中物体移动拖影

2023-10-08 22:30
文章标签 移动 物体 unity3d 拖影

本文主要是介绍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中物体移动拖影的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/168420

相关文章

C++ 右值引用(rvalue references)与移动语义(move semantics)深度解析

《C++右值引用(rvaluereferences)与移动语义(movesemantics)深度解析》文章主要介绍了C++右值引用和移动语义的设计动机、基本概念、实现方式以及在实际编程中的应用,... 目录一、右值引用(rvalue references)与移动语义(move semantics)设计动机1

使用Python实现在PDF中添加、导入、复制、移动与删除页面

《使用Python实现在PDF中添加、导入、复制、移动与删除页面》在日常办公和自动化任务中,我们经常需要对PDF文件进行页面级的编辑,使用Python,你可以轻松实现这些操作,而无需依赖AdobeAc... 目录1. 向 PDF 添加空白页2. 从另一个 PDF 导入页面3. 删除 PDF 中的页面4. 在

把Python列表中的元素移动到开头的三种方法

《把Python列表中的元素移动到开头的三种方法》在Python编程中,我们经常需要对列表(list)进行操作,有时,我们希望将列表中的某个元素移动到最前面,使其成为第一项,本文给大家介绍了把Pyth... 目录一、查找删除插入法1. 找到元素的索引2. 移除元素3. 插入到列表开头二、使用列表切片(Lis

HTML5实现的移动端购物车自动结算功能示例代码

《HTML5实现的移动端购物车自动结算功能示例代码》本文介绍HTML5实现移动端购物车自动结算,通过WebStorage、事件监听、DOM操作等技术,确保实时更新与数据同步,优化性能及无障碍性,提升用... 目录1. 移动端购物车自动结算概述2. 数据存储与状态保存机制2.1 浏览器端的数据存储方式2.1.

双系统电脑中把Ubuntu装进外接移动固态硬盘的全过程

《双系统电脑中把Ubuntu装进外接移动固态硬盘的全过程》:本文主要介绍如何在Windows11系统中使用VMware17创建虚拟机,并在虚拟机中安装Ubuntu22.04桌面版或Ubunt... 目录一、首先win11中安装vmware17二、磁盘分区三、保存四、使用虚拟机进行系统安装五、遇见的错误和解决

使用FileChannel实现文件的复制和移动方式

《使用FileChannel实现文件的复制和移动方式》:本文主要介绍使用FileChannel实现文件的复制和移动方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录使用 FileChannel 实现文件复制代码解释使用 FileChannel 实现文件移动代码解释

Qt把文件夹从A移动到B的实现示例

《Qt把文件夹从A移动到B的实现示例》本文主要介绍了Qt把文件夹从A移动到B的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录如何移动一个文件? 如何移动文件夹(包含里面的全部内容):如何删除文件夹:QT 文件复制,移动(

Python重命名文件并移动到对应文件夹

《Python重命名文件并移动到对应文件夹》在日常的文件管理和处理过程中,我们可能会遇到需要将文件整理到不同文件夹中的需求,下面我们就来看看如何使用Python实现重命名文件并移动到对应文件夹吧... 目录检查并删除空文件夹1. 基本需求2. 实现代码解析3. 代码解释4. 代码执行结果5. 总结方法补充在

使用C#如何创建人名或其他物体随机分组

《使用C#如何创建人名或其他物体随机分组》文章描述了一个随机分配人员到多个团队的代码示例,包括将人员列表随机化并根据组数分配到不同组,最后按组号排序显示结果... 目录C#创建人名或其他物体随机分组此示例使用以下代码将人员分配到组代码首先将lstPeople ListBox总结C#创建人名或其他物体随机分组

我在移动打工的日志

客户:给我搞一下录音 我:不会。不在服务范围。 客户:是不想吧 我:笑嘻嘻(气笑) 客户:小姑娘明明会,却欺负老人 我:笑嘻嘻 客户:那我交话费 我:手机号 客户:给我搞录音 我:不会。不懂。没搞过。 客户:那我交话费 我:手机号。这是电信的啊!!我这是中国移动!! 客户:我不管,我要充话费,充话费是你们的 我:可是这是移动!!中国移动!! 客户:我这是手机号 我:那又如何,这是移动!你是电信!!