public static GameObject ResolveGuid(System.Guid guid) { if (instance == null) { instance = new GuidManager(); } return(instance.ResolveGuidInternal(guid, null, null)); }
public static GameObject ResolveGuid(System.Guid guid, Action onDestroyCallback) { if (instance == null) { instance = new GuidManager(); } return(instance.ResolveGuidInternal(guid, null, onDestroyCallback)); }
public static GameObject ResolveGuid(System.Guid guid, Action <GameObject> onAddCallback, Action onRemoveCallback) { if (instance == null) { instance = new GuidManager(); } return(instance.ResolveGuidInternal(guid, onAddCallback, onRemoveCallback)); }
public static void Remove(System.Guid guid) { if (instance == null) { instance = new GuidManager(); } instance.InternalRemove(guid); }
// All the public API is static so you need not worry about creating an instance public static bool Add(GuidComponent guidComponent) { if (instance == null) { instance = new GuidManager(); } return(instance.InternalAdd(guidComponent)); }
// When de-serializing or creating this component, we want to either restore our serialized GUID // or create a new one. private void CreateGuid() { // if our serialized data is invalid, then we are a new object and need a new GUID if (this.serializedGuid == null || this.serializedGuid.Length != 16) { #if UNITY_EDITOR // if in editor, make sure we aren't a prefab of some kind if (this.IsAssetOnDisk()) { return; } Undo.RecordObject(this, "Added GUID"); #endif this.guid = System.Guid.NewGuid(); this.serializedGuid = this.guid.ToByteArray(); #if UNITY_EDITOR // If we are creating a new GUID for a prefab instance of a prefab, but we have somehow lost our prefab connection // force a save of the modified prefab instance properties if (PrefabUtility.IsPartOfNonAssetPrefabInstance(this)) { PrefabUtility.RecordPrefabInstancePropertyModifications(this); } #endif } else if (this.guid == System.Guid.Empty) { // otherwise, we should set our system guid to our serialized guid this.guid = new System.Guid(this.serializedGuid); } // register with the GUID Manager so that other components can access this if (this.guid != System.Guid.Empty) { if (!GuidManager.Add(this)) { // if registration fails, we probably have a duplicate or invalid GUID, get us a new one. this.serializedGuid = null; this.guid = System.Guid.Empty; this.CreateGuid(); } } }
// Let the manager know we are gone, so other objects no longer find this public void OnDestroy() { GuidManager.Remove(this.guid); }
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { guidProp = property.FindPropertyRelative("serializedGuid"); nameProp = property.FindPropertyRelative("cachedName"); sceneProp = property.FindPropertyRelative("cachedScene"); // Using BeginProperty / EndProperty on the parent property means that // prefab override logic works on the entire property. EditorGUI.BeginProperty(position, label, property); position.height = EditorGUIUtility.singleLineHeight; // Draw prefix label, returning the new rect we can draw in var guidCompPosition = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label); System.Guid currentGuid; GameObject currentGO = null; // working with array properties is a bit unwieldy // you have to get the property at each index manually byte[] byteArray = new byte[16]; int arraySize = guidProp.arraySize; for (int i = 0; i < arraySize; ++i) { var byteProp = guidProp.GetArrayElementAtIndex(i); byteArray[i] = (byte)byteProp.intValue; } currentGuid = new System.Guid(byteArray); currentGO = GuidManager.ResolveGuid(currentGuid); GuidComponent currentGuidComponent = currentGO != null?currentGO.GetComponent <GuidComponent>() : null; GuidComponent component = null; if (currentGuid != System.Guid.Empty && currentGuidComponent == null) { // if our reference is set, but the target isn't loaded, we display the target and the scene it is in, and provide a way to clear the reference float buttonWidth = 55.0f; guidCompPosition.xMax -= buttonWidth; bool guiEnabled = GUI.enabled; GUI.enabled = false; EditorGUI.LabelField(guidCompPosition, new GUIContent(nameProp.stringValue, "Target GameObject is not currently loaded."), EditorStyles.objectField); GUI.enabled = guiEnabled; Rect clearButtonRect = new Rect(guidCompPosition); clearButtonRect.xMin = guidCompPosition.xMax; clearButtonRect.xMax += buttonWidth; if (GUI.Button(clearButtonRect, clearButtonGUI, EditorStyles.miniButton)) { ClearPreviousGuid(); } } else { // if our object is loaded, we can simply use an object field directly component = EditorGUI.ObjectField(guidCompPosition, currentGuidComponent, typeof(GuidComponent), true) as GuidComponent; } if (currentGuidComponent != null && component == null) { ClearPreviousGuid(); } // if we have a valid reference, draw the scene name of the scene it lives in so users can find it if (component != null) { nameProp.stringValue = component.name; string scenePath = component.gameObject.scene.path; sceneProp.objectReferenceValue = AssetDatabase.LoadAssetAtPath <SceneAsset>(scenePath); // only update the GUID Prop if something changed. This fixes multi-edit on GUID References if (component != currentGuidComponent) { byteArray = component.GetGuid().ToByteArray(); arraySize = guidProp.arraySize; for (int i = 0; i < arraySize; ++i) { var byteProp = guidProp.GetArrayElementAtIndex(i); byteProp.intValue = byteArray[i]; } } } EditorGUI.indentLevel++; position.y += EditorGUIUtility.singleLineHeight; bool cachedGUIState = GUI.enabled; GUI.enabled = false; EditorGUI.ObjectField(position, sceneLabel, sceneProp.objectReferenceValue, typeof(SceneAsset), false); GUI.enabled = cachedGUIState; EditorGUI.indentLevel--; EditorGUI.EndProperty(); }