IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> Unity如何制作3D人物残影——实现黑客帝国的躲子弹镜头 -> 正文阅读

[游戏开发]Unity如何制作3D人物残影——实现黑客帝国的躲子弹镜头

在这里插入图片描述

public abstract class AfterImage3D : MonoBehaviour
{
    public abstract void Play();
    //我想了三种方式
    //1.获取当前动画以及播放了多长时间,然后实例化一个仅有渲染功能的预制体,让他播放这一帧并暂停动画
    //2.直接克隆当前游戏对象,再清除他与渲染无关的组件并改变材质
    //3.直接调用全局绘制网格的方法
}
public class AdventurerController : MonoBehaviour
{
    private Animator animator;
    private AfterImage3D afterImage3D;

    private void Awake()
    {
        animator = GetComponent<Animator>();
        afterImage3D = GetComponent<AfterImage3D>();
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            animator.Play("swordStrike1");
            afterImage3D.Play();
        }
    }
}

方式1:

public class AfterImage3DByAnimation : AfterImage3D
{
    public AfterImageObject afterImagePrefab;
	//在一段时间呢隔一段时间生成一个残影
    public float Duration = 5;
    public float Interval = 0.2f;

    private float mTime = 5;

    private Animator animator;
    private List<AfterImageObject> afterImageObjects = new List<AfterImageObject>();

    private void Awake()
    {
        animator = GetComponent<Animator>();
    }

    public override void Play()
    {
        if (GetComponentsInChildren<Renderer>().Length <= 0)
        {
            return;
        }

        mTime = Duration;
        StartCoroutine(AddAfterImage());
    }

    IEnumerator AddAfterImage()
    {
        while (mTime > 0)
        {
            CreateImage();
            yield return new WaitForSeconds(Interval);
            mTime -= Interval;
        }
        yield return null;
    }

    private void CreateImage()
    {
        if (animator.GetCurrentAnimatorClipInfoCount(0) > 0) 
        {
            string currentAnimationName = animator.GetCurrentAnimatorClipInfo(0)[0].clip.name;
            float currentAnimationTime = animator.GetCurrentAnimatorStateInfo(0).normalizedTime;
            for (int i = 0; i < afterImageObjects.Count; i++)
            {
                if (!afterImageObjects[i].gameObject.activeSelf)
                {
                    afterImageObjects[i].Play(currentAnimationName, currentAnimationTime);
                    return;
                }
            }
            AfterImageObject clone = Instantiate(afterImagePrefab, transform.position, transform.rotation);
            clone.Play(currentAnimationName, currentAnimationTime);
            afterImageObjects.Add(clone);
        }
        
    }
}

public class AfterImageObject : MonoBehaviour
{
    private Animator animator;
	//所有要生成残影的渲染组件
    public Renderer[] renderers;
	//对应的透明材质
    public Material[] materials;
	//渐隐时长
    public float FadeoutTime = 1;
	
    private Material[] tempMaterials;

    private float time = 1;
	//改变动画速度来制作更细节的残影
    public bool useDelay;
    [Range(0, 1)]
    public float delaySpeed;
    
    public void Play(string animName, float normalizeTime) 
    {
        if (animator == null) 
        {
            animator = GetComponent<Animator>();
            tempMaterials = new Material[renderers.Length];
            for (int i = 0; i < renderers.Length; i++)
            {
                tempMaterials[i] = new Material(materials[i]);
                renderers[i].material = tempMaterials[i];
                renderers[i].shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
            }
        }
        gameObject.SetActive(true);
        animator.Play(animName, 0, normalizeTime);
        animator.speed = useDelay ? delaySpeed : 0;
        time = FadeoutTime;
    }

    void LateUpdate()
    {
        time -= Time.deltaTime;
        for (int i = 0; i < tempMaterials.Length; i++)
        {
            if (tempMaterials[i].HasProperty("_Color"))
            {
                Color color = Color.white;
                color.a = Mathf.Max(0, time / FadeoutTime);
                tempMaterials[i].SetColor("_Color", color);
            }
        }

        if (time <= 0) 
        {
            for (int i = 0; i < tempMaterials.Length; i++)
            {
                if (tempMaterials[i].HasProperty("_Color"))
                {
                    tempMaterials[i].SetColor("_Color", materials[i].GetColor("_Color"));
                }
            }
            gameObject.SetActive(false);
        }
    }
}

方式三:

public class AfterImage3DByCombine : AfterImage3D
{
    public class AfterImange
    {
        public Mesh mesh;
        public Material material;
        public Matrix4x4 matrix;
        public float duration;
        public float time;
    }

    protected SkinnedMeshRenderer[] skinRenderers;
    protected MeshFilter[] filters;
    protected int filtersCount = 0;

    public bool IncludeMeshFilter = true;
    public Material EffectMaterial;

    public float Duration = 5;
    public float Interval = 0.2f;
    public float FadeoutTime = 1;

    private float mTime = 5;
    private List<AfterImange> mAfterImageList = new List<AfterImange>();

    protected virtual void Awake()
    {
        skinRenderers = GetComponentsInChildren<SkinnedMeshRenderer>();
        if (IncludeMeshFilter)
        {
            filters = GetComponentsInChildren<MeshFilter>();
            filtersCount = filters.Length;
        }
    }

    public override void Play()
    {
        if (skinRenderers.Length + filtersCount <= 0)
        {
            return;
        }

        mTime = Duration;
        StartCoroutine(AddAfterImage());
    }

    IEnumerator AddAfterImage()
    {
        while (mTime > 0)
        {
            CreateImage();
            yield return new WaitForSeconds(Interval);
            mTime -= Interval;
        }
        yield return null;
    }

    void CreateImage()
    {
        CombineInstance[] combineInstances = new CombineInstance[skinRenderers.Length + filtersCount];

        int index = 0;
        for (int i = 0; i < skinRenderers.Length; i++)
        {
            var render = skinRenderers[i];
            var mesh = new Mesh();
            render.BakeMesh(mesh);
            combineInstances[index] = new CombineInstance
            {
                mesh = mesh,
                transform = render.gameObject.transform.localToWorldMatrix,
                subMeshIndex = 0
            };

            index++;
        }

        for (int i = 0; i < filtersCount; i++)
        {
            var render = filters[i];
            var temp = (render.sharedMesh != null) ? render.sharedMesh : render.mesh;
            var mesh = (Mesh)Instantiate(temp);
            combineInstances[index] = new CombineInstance
            {
                mesh = mesh,
                transform = render.gameObject.transform.localToWorldMatrix,
                subMeshIndex = 0
            };

            index++;
        }

        Mesh combinedMesh = new Mesh();
        combinedMesh.CombineMeshes(combineInstances, true, true);

        mAfterImageList.Add(new AfterImange
        {
            mesh = combinedMesh,
            material = new Material(EffectMaterial),
            time = FadeoutTime,
            duration = FadeoutTime,
        });
    }

    void LateUpdate()
    {
        bool needRemove = false;
        foreach (var image in mAfterImageList)
        {
            image.time -= Time.deltaTime;
            if (image.material.HasProperty("_Color"))
            {
                Color color = Color.white;
                color.a = Mathf.Max(0, image.time / image.duration);
                image.material.SetColor("_Color", color);
            }
            //public static void DrawMesh(Mesh mesh, Matrix4x4 matrix, Material material, int layer, Camera camera, int submeshIndex, MaterialPropertyBlock properties, ShadowCastingMode castShadows);
            Graphics.DrawMesh(image.mesh, Matrix4x4.identity, image.material, gameObject.layer, null, 0, null, false);
            if (image.time <= 0)
            {
                needRemove = true;
            }
        }

        if (needRemove)
        {
            mAfterImageList.RemoveAll(x => x.time <= 0);
        }
    }


}

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-12-26 22:33:05  更:2021-12-26 22:35:19 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/17 1:36:31-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码