using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ModelHighlight : MonoBehaviour
{
///
/// 高亮的颜色
///
public Color highLightColor = new Color(0.5f, 0.5f, 0.5f, 1);
///
/// 高亮边缘 宽度
///
[Range(0.001f, 0.005f)]
public float lineWidth = 0.005f;
///
/// 高亮边缘 偏移调整
///
[Range(0, 2)]
public float lineAjustMeng = 0.5f;
///
/// 闪烁效果速度 0则不闪烁
///
[Range(0, 10)]
public float highLightSpeed = 3f;
///
/// 单例
///
public static ModelHighlight instance;
///
/// 高亮 skinmesh数组
///
private SkinnedMeshRenderer[] highlightSkinnedRenderers;
private SkinnedMeshRenderer[] existingSkinnedRenderers;
///
/// 高亮 普通mesh数组
///
private MeshRenderer[] highlightRenderers;
private MeshRenderer[] existingRenderers;
///
/// 不需要高亮模型 数组
///
public GameObject[] hideHighlight;
void Awake()
{
instance = this;
}
void Start()
{
}
void Update()
{
}
///
/// 模型高亮
///
/// 目标高亮父节点 所有子节点都会高亮
/// 模型是否 需要高亮 true-高亮 false-关闭高亮
public void SetModelHighlight(GameObject target ,bool isHighlight)
{
existingSkinnedRenderers = target.GetComponentsInChildren(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();
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(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();
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();
newFilter.sharedMesh = existingFilter.sharedMesh;
MeshRenderer newRenderer = newFilterHolder.AddComponent();
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);
}
}
}
}
///
/// 改变模型高亮颜色
///
/// 目标模型 所有子节点模型高亮颜色都会改变
/// 改变的颜色 RGB
public void ChangeModelHighlightColor(GameObject target, Color color)
{
existingSkinnedRenderers = target.GetComponentsInChildren(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().materials[0].SetColor("g_vOutlineColor", color);
continue;
}
}
MeshFilter[] existingFilters = target.GetComponentsInChildren(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().materials[0].SetColor("g_vOutlineColor", color);
continue;
}
}
}
///
/// 改变高亮模型闪烁的速度
///
/// 目标模型 所有子节点模型高亮闪烁速度都会改变
/// 闪烁速度 0-停止闪烁 速度越大闪烁越快
public void ChangeModelHighlightSpeed(GameObject target, float speed)
{
existingSkinnedRenderers = target.GetComponentsInChildren(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().materials[0].SetFloat("_FlickerTime", speed);
continue;
}
}
MeshFilter[] existingFilters = target.GetComponentsInChildren(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().materials[0].SetFloat("_FlickerTime", speed);
continue;
}
}
}
///
/// 需要 隐藏高亮模型操作
///
///
///
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;
}
///
/// 生成材质球
///
///
///
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;
}
}