using System.Collections.Generic; using Games.LogicObj; using Module.Log; using UnityEngine; using UnityEngine.Rendering; /// /// 用于渲染透视效果的特殊渲染器 /// public class XRayRenderer : MonoBehaviour { private static Material _xRayMaterial; private const string _xRayMaterialName = "PlayerXRay"; private List> _skinnedMeshRendererList; private List _meshRendererList; // 注:不要修改为Start,需要保证在有子节点绑定前配置完成 public void Init(List rendererInfos) { for (var i = 0; i < rendererInfos.Count; i++) { var cachedRenderer = rendererInfos[i].CachedRenderer; if (cachedRenderer == null || cachedRenderer.sharedMaterial == null || cachedRenderer.sharedMaterial.shader == null || !cachedRenderer.sharedMaterial.shader.IsCharacterShader()) continue; var meshRenderer = rendererInfos[i].CachedRenderer as MeshRenderer; if (meshRenderer == null) { var skinRenderer = rendererInfos[i].CachedRenderer as SkinnedMeshRenderer; if (skinRenderer != null) { if (_skinnedMeshRendererList == null) _skinnedMeshRendererList = new List>(); _skinnedMeshRendererList.Add( new MyTuple(skinRenderer, CreateFromSkinnedRenderer(skinRenderer))); } } else { var meshFilter = meshRenderer.GetComponent(); if (meshFilter != null) { if (_meshRendererList == null) _meshRendererList = new List(); _meshRendererList.Add(CreateFromMeshRenderer(meshRenderer, meshFilter)); } #if UNITY_EDITOR else LogModule.ErrorLog(string.Format("MeshRenderer没有对应的MeshFilter,于物体{0}", meshRenderer.transform.GetHierarchyName())); #endif } } } public void TrimXRaRenderer(Transform root) { if (root != null) { if (_skinnedMeshRendererList != null) { for (var i = _skinnedMeshRendererList.Count - 1; i >= 0; i--) { if (_skinnedMeshRendererList[i].first == null || _skinnedMeshRendererList[i].first.transform.IsChildOf(root)) _skinnedMeshRendererList.RemoveAt(i); } } if (_meshRendererList != null) { for (var i = _meshRendererList.Count - 1; i >= 0; i--) { if (_meshRendererList[i] == null || _meshRendererList[i].transform.IsChildOf(root)) _meshRendererList.RemoveAt(i); } } } } public void ResetBones() { if (_skinnedMeshRendererList != null) for (var i = _skinnedMeshRendererList.Count - 1; i >= 0; i--) { SetBones(_skinnedMeshRendererList[i].first, _skinnedMeshRendererList[i].second); _skinnedMeshRendererList[i].second.gameObject.SetActive(true); } if (_meshRendererList != null) for (var i = 0; i < _meshRendererList.Count; i++) _meshRendererList[i].gameObject.SetActive(true); } public void Hide() { if (_skinnedMeshRendererList != null) for (var i = 0; i < _skinnedMeshRendererList.Count; i++) _skinnedMeshRendererList[i].second.gameObject.SetActive(false); if (_meshRendererList != null) for (var i = 0; i < _meshRendererList.Count; i++) _meshRendererList[i].gameObject.SetActive(false); } private static MeshRenderer CreateFromMeshRenderer(MeshRenderer sourceRenderer, MeshFilter sourceFilter) { // 注:可能有些物体会拥有初始动画 var xRayObject = BuildXRayObject(sourceRenderer); var targetFilter = xRayObject.AddComponent(); var targetRenderer = xRayObject.AddComponent(); targetFilter.sharedMesh = sourceFilter.sharedMesh; SetRendererParameters(sourceRenderer, targetRenderer); return targetRenderer; } private static SkinnedMeshRenderer CreateFromSkinnedRenderer(SkinnedMeshRenderer sourceRenderer) { var xRayObject = BuildXRayObject(sourceRenderer); var targetRenderer = xRayObject.AddComponent(); SetBones(sourceRenderer, targetRenderer); targetRenderer.sharedMesh = sourceRenderer.sharedMesh; SetRendererParameters(sourceRenderer, targetRenderer); return targetRenderer; } private static void SetBones(SkinnedMeshRenderer sourceRenderer, SkinnedMeshRenderer targetRenderer) { targetRenderer.rootBone = sourceRenderer.rootBone; targetRenderer.bones = sourceRenderer.bones; } private static GameObject BuildXRayObject(Component root) { var xRayObject = new GameObject("XRayObject"); xRayObject.transform.SetParent(root.transform); xRayObject.transform.localPosition = Vector3.zero; xRayObject.transform.localRotation = Quaternion.identity; xRayObject.transform.localScale = Vector3.one; return xRayObject; } private static void SetRendererParameters(Renderer source, Renderer target) { if (_xRayMaterial == null) _xRayMaterial = CommonUtility.LoadSharedMaterial(_xRayMaterialName); target.shadowCastingMode = ShadowCastingMode.Off; target.receiveShadows = false; var materials = new Material[source.sharedMaterials.Length]; for (var i = 0; i < materials.Length; i++) materials[i] = _xRayMaterial; target.sharedMaterials = materials; target.motionVectorGenerationMode = MotionVectorGenerationMode.ForceNoMotion; } }