292 lines
12 KiB
C#
292 lines
12 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
public class ModelHighlight : MonoBehaviour
|
|
{
|
|
/// <summary>
|
|
/// 高亮的颜色
|
|
/// </summary>
|
|
public Color highLightColor = new Color(0.5f, 0.5f, 0.5f, 1);
|
|
|
|
/// <summary>
|
|
/// 高亮边缘 宽度
|
|
/// </summary>
|
|
[Range(0.001f, 0.005f)]
|
|
public float lineWidth = 0.005f;
|
|
|
|
/// <summary>
|
|
/// 高亮边缘 偏移调整
|
|
/// </summary>
|
|
[Range(0, 2)]
|
|
public float lineAjustMeng = 0.5f;
|
|
|
|
/// <summary>
|
|
/// 闪烁效果速度 0则不闪烁
|
|
/// </summary>
|
|
[Range(0, 10)]
|
|
public float highLightSpeed = 3f;
|
|
|
|
/// <summary>
|
|
/// 单例
|
|
/// </summary>
|
|
public static ModelHighlight instance;
|
|
|
|
/// <summary>
|
|
/// 高亮 skinmesh数组
|
|
/// </summary>
|
|
private SkinnedMeshRenderer[] highlightSkinnedRenderers;
|
|
private SkinnedMeshRenderer[] existingSkinnedRenderers;
|
|
|
|
/// <summary>
|
|
/// 高亮 普通mesh数组
|
|
/// </summary>
|
|
private MeshRenderer[] highlightRenderers;
|
|
private MeshRenderer[] existingRenderers;
|
|
|
|
/// <summary>
|
|
/// 不需要高亮模型 数组
|
|
/// </summary>
|
|
public GameObject[] hideHighlight;
|
|
|
|
void Awake()
|
|
{
|
|
instance = this;
|
|
}
|
|
|
|
void Start()
|
|
{
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// 模型高亮
|
|
/// </summary>
|
|
/// <param name="target"> 目标高亮父节点 所有子节点都会高亮 </param>
|
|
/// <param name="isHighlight"> 模型是否 需要高亮 true-高亮 false-关闭高亮 </param>
|
|
public void SetModelHighlight(GameObject target ,bool isHighlight)
|
|
{
|
|
existingSkinnedRenderers = target.GetComponentsInChildren<SkinnedMeshRenderer>(true);
|
|
highlightSkinnedRenderers = new SkinnedMeshRenderer[existingSkinnedRenderers.Length];
|
|
Material highlightMat = CreatMaterial(highLightColor);
|
|
|
|
for (int skinnedIndex = 0; skinnedIndex < existingSkinnedRenderers.Length; skinnedIndex++)
|
|
{
|
|
if (existingSkinnedRenderers[skinnedIndex].transform.name.Contains("_Highlight"))
|
|
{
|
|
continue;
|
|
}
|
|
if (isHighlight)
|
|
{
|
|
if (existingSkinnedRenderers[skinnedIndex].transform.Find(existingSkinnedRenderers[skinnedIndex].transform.name + "_Highlight"))
|
|
{
|
|
existingSkinnedRenderers[skinnedIndex].transform.Find(existingSkinnedRenderers[skinnedIndex].transform.name + "_Highlight").gameObject.SetActive(true);
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
SkinnedMeshRenderer existingSkinned = existingSkinnedRenderers[skinnedIndex];
|
|
if (ShouldIgnoreHighlight(existingSkinned))
|
|
continue;
|
|
|
|
GameObject newSkinnedHolder = new GameObject("SkinnedHolder");
|
|
newSkinnedHolder.name = existingSkinned.transform.name + "_Highlight";
|
|
newSkinnedHolder.transform.parent = existingSkinned.transform;
|
|
newSkinnedHolder.transform.localPosition = Vector3.zero;
|
|
newSkinnedHolder.transform.localEulerAngles = Vector3.zero;
|
|
newSkinnedHolder.transform.localScale = Vector3.one;
|
|
SkinnedMeshRenderer newSkinned = newSkinnedHolder.AddComponent<SkinnedMeshRenderer>();
|
|
Material[] materials = new Material[existingSkinned.sharedMaterials.Length];
|
|
for (int materialIndex = 0; materialIndex < materials.Length; materialIndex++)
|
|
{
|
|
materials[materialIndex] = highlightMat;
|
|
}
|
|
|
|
newSkinned.sharedMaterials = materials;
|
|
newSkinned.sharedMesh = existingSkinned.sharedMesh;
|
|
newSkinned.rootBone = existingSkinned.rootBone;
|
|
newSkinned.updateWhenOffscreen = existingSkinned.updateWhenOffscreen;
|
|
newSkinned.bones = existingSkinned.bones;
|
|
|
|
highlightSkinnedRenderers[skinnedIndex] = newSkinned;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (existingSkinnedRenderers[skinnedIndex].transform.Find(existingSkinnedRenderers[skinnedIndex].transform.name + "_Highlight"))
|
|
{
|
|
existingSkinnedRenderers[skinnedIndex].transform.Find(existingSkinnedRenderers[skinnedIndex].transform.name + "_Highlight").gameObject.SetActive(false);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
MeshFilter[] existingFilters = target.GetComponentsInChildren<MeshFilter>(true);
|
|
existingRenderers = new MeshRenderer[existingFilters.Length];
|
|
highlightRenderers = new MeshRenderer[existingFilters.Length];
|
|
|
|
for (int filterIndex = 0; filterIndex < existingFilters.Length; filterIndex++)
|
|
{
|
|
if (existingFilters[filterIndex].transform.name.Contains("_Highlight"))
|
|
{
|
|
continue;
|
|
}
|
|
if (isHighlight)
|
|
{
|
|
if (existingFilters[filterIndex].transform.Find(existingFilters[filterIndex].transform.name + "_Highlight"))
|
|
{
|
|
existingFilters[filterIndex].transform.Find(existingFilters[filterIndex].transform.name + "_Highlight").gameObject.SetActive(true);
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
|
|
MeshFilter existingFilter = existingFilters[filterIndex];
|
|
MeshRenderer existingRenderer = existingFilter.GetComponent<MeshRenderer>();
|
|
|
|
if (existingFilter == null || existingRenderer == null || ShouldIgnoreHighlight(existingFilter))
|
|
continue;
|
|
|
|
GameObject newFilterHolder = new GameObject("FilterHolder");
|
|
newFilterHolder.name = existingFilter.transform.name + "_Highlight";
|
|
newFilterHolder.transform.parent = existingFilter.transform;
|
|
newFilterHolder.transform.localPosition = Vector3.zero;
|
|
newFilterHolder.transform.localEulerAngles = Vector3.zero;
|
|
newFilterHolder.transform.localScale = Vector3.one;
|
|
MeshFilter newFilter = newFilterHolder.AddComponent<MeshFilter>();
|
|
newFilter.sharedMesh = existingFilter.sharedMesh;
|
|
MeshRenderer newRenderer = newFilterHolder.AddComponent<MeshRenderer>();
|
|
|
|
Material[] materials = new Material[existingRenderer.sharedMaterials.Length];
|
|
for (int materialIndex = 0; materialIndex < materials.Length; materialIndex++)
|
|
{
|
|
materials[materialIndex] = highlightMat;
|
|
}
|
|
newRenderer.sharedMaterials = materials;
|
|
|
|
highlightRenderers[filterIndex] = newRenderer;
|
|
existingRenderers[filterIndex] = existingRenderer;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (existingFilters[filterIndex].transform.Find(existingFilters[filterIndex].transform.name + "_Highlight"))
|
|
{
|
|
existingFilters[filterIndex].transform.Find(existingFilters[filterIndex].transform.name + "_Highlight").gameObject.SetActive(false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 改变模型高亮颜色
|
|
/// </summary>
|
|
/// <param name="target"> 目标模型 所有子节点模型高亮颜色都会改变 </param>
|
|
/// <param name="color"> 改变的颜色 RGB </param>
|
|
public void ChangeModelHighlightColor(GameObject target, Color color)
|
|
{
|
|
existingSkinnedRenderers = target.GetComponentsInChildren<SkinnedMeshRenderer>(true);
|
|
highlightSkinnedRenderers = new SkinnedMeshRenderer[existingSkinnedRenderers.Length];
|
|
|
|
for (int skinnedIndex = 0; skinnedIndex < existingSkinnedRenderers.Length; skinnedIndex++)
|
|
{
|
|
if (existingSkinnedRenderers[skinnedIndex].transform.Find(existingSkinnedRenderers[skinnedIndex].transform.name + "_Highlight"))
|
|
{
|
|
existingSkinnedRenderers[skinnedIndex].transform.Find(existingSkinnedRenderers[skinnedIndex].transform.name + "_Highlight").
|
|
gameObject.GetComponent<MeshRenderer>().materials[0].SetColor("g_vOutlineColor", color);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
MeshFilter[] existingFilters = target.GetComponentsInChildren<MeshFilter>(true);
|
|
existingRenderers = new MeshRenderer[existingFilters.Length];
|
|
highlightRenderers = new MeshRenderer[existingFilters.Length];
|
|
|
|
for (int filterIndex = 0; filterIndex < existingFilters.Length; filterIndex++)
|
|
{
|
|
if (existingFilters[filterIndex].transform.Find(existingFilters[filterIndex].transform.name + "_Highlight"))
|
|
{
|
|
existingFilters[filterIndex].transform.Find(existingFilters[filterIndex].transform.name + "_Highlight").
|
|
gameObject.GetComponent<MeshRenderer>().materials[0].SetColor("g_vOutlineColor", color);
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 改变高亮模型闪烁的速度
|
|
/// </summary>
|
|
/// <param name="target"> 目标模型 所有子节点模型高亮闪烁速度都会改变 </param>
|
|
/// <param name="speed"> 闪烁速度 0-停止闪烁 速度越大闪烁越快 </param>
|
|
public void ChangeModelHighlightSpeed(GameObject target, float speed)
|
|
{
|
|
existingSkinnedRenderers = target.GetComponentsInChildren<SkinnedMeshRenderer>(true);
|
|
highlightSkinnedRenderers = new SkinnedMeshRenderer[existingSkinnedRenderers.Length];
|
|
|
|
for (int skinnedIndex = 0; skinnedIndex < existingSkinnedRenderers.Length; skinnedIndex++)
|
|
{
|
|
if (existingSkinnedRenderers[skinnedIndex].transform.Find(existingSkinnedRenderers[skinnedIndex].transform.name + "_Highlight"))
|
|
{
|
|
existingSkinnedRenderers[skinnedIndex].transform.Find(existingSkinnedRenderers[skinnedIndex].transform.name + "_Highlight").
|
|
gameObject.GetComponent<MeshRenderer>().materials[0].SetFloat("_FlickerTime", speed);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
MeshFilter[] existingFilters = target.GetComponentsInChildren<MeshFilter>(true);
|
|
existingRenderers = new MeshRenderer[existingFilters.Length];
|
|
highlightRenderers = new MeshRenderer[existingFilters.Length];
|
|
|
|
for (int filterIndex = 0; filterIndex < existingFilters.Length; filterIndex++)
|
|
{
|
|
if (existingFilters[filterIndex].transform.Find(existingFilters[filterIndex].transform.name + "_Highlight"))
|
|
{
|
|
existingFilters[filterIndex].transform.Find(existingFilters[filterIndex].transform.name + "_Highlight").
|
|
gameObject.GetComponent<MeshRenderer>().materials[0].SetFloat("_FlickerTime", speed);
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 需要 隐藏高亮模型操作
|
|
/// </summary>
|
|
/// <param name="component"></param>
|
|
/// <returns></returns>
|
|
private bool ShouldIgnoreHighlight(Component component)
|
|
{
|
|
return ShouldIgnore(component.gameObject);
|
|
}
|
|
|
|
private bool ShouldIgnore(GameObject check)
|
|
{
|
|
for (int ignoreIndex = 0; ignoreIndex < hideHighlight.Length; ignoreIndex++)
|
|
{
|
|
if (check == hideHighlight[ignoreIndex])
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 生成材质球
|
|
/// </summary>
|
|
/// <param name="color"></param>
|
|
/// <returns></returns>
|
|
private Material CreatMaterial(Color color)
|
|
{
|
|
Material tempMat = new Material(Shader.Find("Highlight/Silhouette"));
|
|
tempMat.SetColor("g_vOutlineColor", color);
|
|
tempMat.SetFloat("g_flOutlineWidth", lineWidth);
|
|
tempMat.SetFloat("g_flCornerAdjust", lineAjustMeng);
|
|
tempMat.SetFloat("_FlickerTime", highLightSpeed);
|
|
return tempMat;
|
|
}
|
|
}
|