102 lines
2.9 KiB
C#
102 lines
2.9 KiB
C#
|
|
using UnityEngine;
|
|||
|
|
using System;
|
|||
|
|
|
|||
|
|
#if UNITY_EDITOR
|
|||
|
|
using UnityEditor;
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
// This call is the type used by any other code to hold a reference to an object by GUID
|
|||
|
|
// If the target object is loaded, it will be returned, otherwise, NULL will be returned
|
|||
|
|
// This always works in Game Objects, so calling code will need to use GetComponent<>
|
|||
|
|
// or other methods to track down the specific objects need by any given system
|
|||
|
|
|
|||
|
|
// Ideally this would be a struct, but we need the ISerializationCallbackReciever
|
|||
|
|
[System.Serializable]
|
|||
|
|
public class GuidReference : ISerializationCallbackReceiver
|
|||
|
|
{
|
|||
|
|
// cache the referenced Game Object if we find one for performance
|
|||
|
|
private GameObject cachedReference;
|
|||
|
|
private bool isCacheSet;
|
|||
|
|
|
|||
|
|
// store our GUID in a form that Unity can save
|
|||
|
|
[SerializeField]
|
|||
|
|
private byte[] serializedGuid;
|
|||
|
|
private System.Guid guid;
|
|||
|
|
|
|||
|
|
#if UNITY_EDITOR
|
|||
|
|
// decorate with some extra info in Editor so we can inform a user of what that GUID means
|
|||
|
|
[SerializeField]
|
|||
|
|
private string cachedName;
|
|||
|
|
[SerializeField]
|
|||
|
|
private SceneAsset cachedScene;
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
// Set up events to let users register to cleanup their own cached references on destroy or to cache off values
|
|||
|
|
public event Action<GameObject> OnGuidAdded = delegate (GameObject go) { };
|
|||
|
|
public event Action OnGuidRemoved = delegate() { };
|
|||
|
|
|
|||
|
|
// create concrete delegates to avoid boxing.
|
|||
|
|
// When called 10,000 times, boxing would allocate ~1MB of GC Memory
|
|||
|
|
private Action<GameObject> addDelegate;
|
|||
|
|
private Action removeDelegate;
|
|||
|
|
|
|||
|
|
// optimized accessor, and ideally the only code you ever call on this class
|
|||
|
|
public GameObject gameObject
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
if( isCacheSet )
|
|||
|
|
{
|
|||
|
|
return cachedReference;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
cachedReference = GuidManager.ResolveGuid( guid, addDelegate, removeDelegate );
|
|||
|
|
isCacheSet = true;
|
|||
|
|
return cachedReference;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private set {}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public GuidReference() { }
|
|||
|
|
|
|||
|
|
public GuidReference(GuidComponent target)
|
|||
|
|
{
|
|||
|
|
guid = target.GetGuid();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void GuidAdded(GameObject go)
|
|||
|
|
{
|
|||
|
|
cachedReference = go;
|
|||
|
|
OnGuidAdded(go);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void GuidRemoved()
|
|||
|
|
{
|
|||
|
|
cachedReference = null;
|
|||
|
|
isCacheSet = false;
|
|||
|
|
OnGuidRemoved();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//convert system guid to a format unity likes to work with
|
|||
|
|
public void OnBeforeSerialize()
|
|||
|
|
{
|
|||
|
|
serializedGuid = guid.ToByteArray();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// convert from byte array to system guid and reset state
|
|||
|
|
public void OnAfterDeserialize()
|
|||
|
|
{
|
|||
|
|
cachedReference = null;
|
|||
|
|
isCacheSet = false;
|
|||
|
|
if (serializedGuid == null || serializedGuid.Length != 16)
|
|||
|
|
{
|
|||
|
|
serializedGuid = new byte[16];
|
|||
|
|
}
|
|||
|
|
guid = new System.Guid(serializedGuid);
|
|||
|
|
addDelegate = GuidAdded;
|
|||
|
|
removeDelegate = GuidRemoved;
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}
|