157 lines
6.2 KiB
C#
157 lines
6.2 KiB
C#
using System.Collections.Generic;
|
||
using Games.LogicObj;
|
||
using Module.Log;
|
||
using UnityEngine;
|
||
using UnityEngine.Rendering;
|
||
|
||
/// <summary>
|
||
/// 用于渲染透视效果的特殊渲染器
|
||
/// </summary>
|
||
public class XRayRenderer : MonoBehaviour
|
||
{
|
||
private static Material _xRayMaterial;
|
||
private const string _xRayMaterialName = "PlayerXRay";
|
||
|
||
private List<MyTuple<SkinnedMeshRenderer, SkinnedMeshRenderer>> _skinnedMeshRendererList;
|
||
private List<MeshRenderer> _meshRendererList;
|
||
|
||
// 注:不要修改为Start,需要保证在有子节点绑定前配置完成
|
||
public void Init(List<RendererInfo> 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<MyTuple<SkinnedMeshRenderer, SkinnedMeshRenderer>>();
|
||
_skinnedMeshRendererList.Add(
|
||
new MyTuple<SkinnedMeshRenderer, SkinnedMeshRenderer>(skinRenderer,
|
||
CreateFromSkinnedRenderer(skinRenderer)));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
var meshFilter = meshRenderer.GetComponent<MeshFilter>();
|
||
if (meshFilter != null)
|
||
{
|
||
if (_meshRendererList == null)
|
||
_meshRendererList = new List<MeshRenderer>();
|
||
|
||
_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<MeshFilter>();
|
||
var targetRenderer = xRayObject.AddComponent<MeshRenderer>();
|
||
targetFilter.sharedMesh = sourceFilter.sharedMesh;
|
||
SetRendererParameters(sourceRenderer, targetRenderer);
|
||
return targetRenderer;
|
||
}
|
||
|
||
private static SkinnedMeshRenderer CreateFromSkinnedRenderer(SkinnedMeshRenderer sourceRenderer)
|
||
{
|
||
var xRayObject = BuildXRayObject(sourceRenderer);
|
||
var targetRenderer = xRayObject.AddComponent<SkinnedMeshRenderer>();
|
||
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;
|
||
}
|
||
} |