您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

151 行
3.7 KiB

using System;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#if UNITY_2021_2_OR_NEWER
using UnityEditor.SceneManagement;
#else
using UnityEditor.Experimental.SceneManagement;
#endif
#endif
namespace Unity.DemoTeam.DigitalHuman
{
[ExecuteAlways, DisallowMultipleComponent]
public abstract class MeshInstanceBehaviour : MonoBehaviour
{
public const string meshInstanceSuffix = "(MeshInstance)";
[HideInInspector]
public Mesh meshAsset;
[NonSerialized]
public Mesh meshInstance;
protected virtual void OnMeshInstanceCreated() { }
protected virtual void OnMeshInstanceDeleted() { }
static bool IsMeshInstance(Mesh mesh)
{
#if UNITY_EDITOR
return (EditorUtility.IsPersistent(mesh) == false);
#else
return (mesh.GetInstanceID() < 0);
#endif
}
public void EnsureMeshInstance()
{
var smr = GetComponent<SkinnedMeshRenderer>();
if (smr != null)
{
if (smr.sharedMesh == null || (IsMeshInstance(smr.sharedMesh) && smr.sharedMesh != meshInstance))
smr.sharedMesh = meshAsset;
if (smr.sharedMesh != null && !IsMeshInstance(smr.sharedMesh))
smr.sharedMesh = EnsureMeshInstanceAux(smr.sharedMesh);
return;
}
var mf = GetComponent<MeshFilter>();
if (mf != null)
{
if (mf.sharedMesh == null || (IsMeshInstance(mf.sharedMesh) && mf.sharedMesh != meshInstance))
mf.sharedMesh = meshAsset;
if (mf.sharedMesh != null && !IsMeshInstance(mf.sharedMesh))
mf.sharedMesh = EnsureMeshInstanceAux(mf.sharedMesh);
return;
}
}
Mesh EnsureMeshInstanceAux(Mesh mesh)
{
if (meshInstance != null)
{
Mesh.DestroyImmediate(meshInstance);
meshInstance = null;
}
meshAsset = mesh;
meshInstance = Mesh.Instantiate(meshAsset);
meshInstance.name = meshAsset.name + meshInstanceSuffix;
meshInstance.hideFlags = HideFlags.HideAndDontSave & ~HideFlags.DontUnloadUnusedAsset;
meshInstance.MarkDynamic();
//Debug.Log("ensureMeshInstance " + meshAsset.name + " -> " + meshInstance.name);
OnMeshInstanceCreated();
return meshInstance;
}
public void RemoveMeshInstance()
{
var smr = GetComponent<SkinnedMeshRenderer>();
if (smr != null)
{
if (smr.sharedMesh == null || IsMeshInstance(smr.sharedMesh))
smr.sharedMesh = meshAsset;
RemoveMeshInstanceAux();
return;
}
var mf = GetComponent<MeshFilter>();
if (mf != null)
{
if (mf.sharedMesh == null || IsMeshInstance(mf.sharedMesh))
mf.sharedMesh = meshAsset;
RemoveMeshInstanceAux();
return;
}
}
void RemoveMeshInstanceAux()
{
if (meshInstance != null)
{
Mesh.DestroyImmediate(meshInstance);
meshInstance = null;
}
OnMeshInstanceDeleted();
}
#if UNITY_EDITOR
static MeshInstanceBehaviour()
{
PrefabStage.prefabSaving += (GameObject prefab) =>
{
var prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
if (prefabStage != null)
{
var meshInstanceBehaviours = prefab.GetComponentsInChildren<MeshInstanceBehaviour>(includeInactive: true);
foreach (var meshInstanceBehaviour in meshInstanceBehaviours)
{
meshInstanceBehaviour.RemoveMeshInstance();
//Debug.Log("reverted mesh instance for " + meshInstanceBehaviour.ToString());
}
}
};
PrefabStage.prefabSaved += (GameObject prefab) =>
{
var prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
if (prefabStage != null)
{
var meshInstanceBehaviours = prefab.GetComponentsInChildren<MeshInstanceBehaviour>(includeInactive: false);
foreach (var meshInstanceBehaviour in meshInstanceBehaviours)
{
meshInstanceBehaviour.EnsureMeshInstance();
//Debug.Log("reinstated mesh instance for " + meshInstanceBehaviour.ToString());
}
}
};
}
#endif
}
}