unity - Snapshot a model to MeshRenderer - 快照一个模型到MeshRenderer

    xiaoxiao2023-11-07  151

    Code

    将以下脚本添加到一个带有Aniamtor Component的模型GameObject上,在Game视图按下"S"键,就可以看到模型给快照了一份出来

    模型要有位移,何移动动画,这样就可以看到快照在原地的样子

    using System.Text; using UnityEngine; public class TestingAnimatorAPI : MonoBehaviour { private MeshRenderer[] meshesRenderer; private SkinnedMeshRenderer[] skinnedMeshesRenderer; private Animator animator; // Start is called before the first frame update void Start() { PrintInfos(); meshesRenderer = transform.GetComponentsInChildren<MeshRenderer>(); skinnedMeshesRenderer = transform.GetComponentsInChildren<SkinnedMeshRenderer>(); } // Update is called once per frame void Update() { if (Input.GetKeyDown(KeyCode.S)) { SnapshotSkinnedMesh(); } } private int counter; private void Snapshot() { GameObject pGo = new GameObject($"SkinnedMeshSnapshot_{++counter}"); pGo.transform.position = gameObject.transform.position; pGo.transform.rotation = gameObject.transform.rotation; pGo.transform.localScale = gameObject.transform.localScale; // meshes if (meshesRenderer != null && meshesRenderer.Length > 0) { for (int i = 0; i < meshesRenderer.Length; i++) { var ownGo = meshesRenderer[i].gameObject; var ownGoMeshFilter = ownGo.GetComponent<MeshFilter>(); GameObject go = new GameObject(meshesRenderer[i].gameObject.name); go.transform.SetParent(pGo.transform); MeshFilter meshFilter = go.AddComponent<MeshFilter>(); MeshRenderer meshRenderer = go.AddComponent<MeshRenderer>(); #if UNITY_EDITOR //go.hideFlags = HideFlags.HideAndDontSave; // 调试时,想在hierarchy看到,就注释掉吧 #else go.hideFlags = HideFlags.HideAndDontSave; #endif meshRenderer.materials = meshesRenderer[i].materials; meshFilter.sharedMesh = ownGoMeshFilter.sharedMesh; go.transform.position = meshesRenderer[i].transform.position; go.transform.rotation = meshesRenderer[i].transform.rotation; go.transform.localScale = meshesRenderer[i].transform.localScale; } } // skinnedMeshes if (skinnedMeshesRenderer != null && skinnedMeshesRenderer.Length > 0) { for (int i = 0; i < skinnedMeshesRenderer.Length; i++) { Mesh mesh = new Mesh(); skinnedMeshesRenderer[i].BakeMesh(mesh); GameObject go = new GameObject(skinnedMeshesRenderer[i].gameObject.name); go.transform.SetParent(pGo.transform); MeshFilter meshFilter = go.AddComponent<MeshFilter>(); MeshRenderer meshRenderer = go.AddComponent<MeshRenderer>(); #if UNITY_EDITOR //go.hideFlags = HideFlags.HideAndDontSave; // 调试时,想在hierarchy看到,就注释掉吧 #else go.hideFlags = HideFlags.HideAndDontSave; #endif meshRenderer.materials = skinnedMeshesRenderer[i].materials; meshFilter.sharedMesh = mesh; go.transform.position = skinnedMeshesRenderer[i].transform.position; go.transform.rotation = skinnedMeshesRenderer[i].transform.rotation; go.transform.localScale = skinnedMeshesRenderer[i].transform.localScale; } } } }

    Runtime

    再Game视图下,按下"S"键,就可以看到Scene下的snapshot效果

    总结

    这个主要实现MeshRenderer的copy,还有SkinnedMeshRenderer的BakeMesh转到MeshRenderer

    还可以优化

    就是在Snapshot之后,可以将所有的Mesh,Material,合并到一个MeshRenderer/Filter来显示,效率更高,这里我就不写了

    应用的场景

    像下面的References中的,制作简单的运动模型的残影效果还有一些,起始出现,或消失时,带有蒙皮动画的,在该蒙皮播放到静止时,可以使用Bake到Mesh,再用MeshRenderer来显示,再合并现实,这样性能将有所提升

    References

    Unity-残影效果实现

    最新回复(0)