I have created a component which generates a GUID which allows me to know what prefab a GameObject instance came from, but when a prefab is duplicated the new prefab simply use the same id as the previous one (which is to be expected). So I would like to know if there is a way to detect when prefabs and objects in general are duplicated so that I can generate a new id.
public class GUID : MonoBehaviour
{
public string idString = System.Guid.NewGuid().ToString("N");
private System.Guid _id;
public System.Guid ID
{
get
{
if (_id == System.Guid.Empty && !string.IsNullOrEmpty(idString))
{
_id = new System.Guid(idString);
}
return _id;
}
}
}
[CustomEditor(typeof(GUID))]
public class GUIDInspector : Editor
{
public override void OnInspectorGUI()
{
GUID guid = target as GUID;
GUILayout.Label("ID: " + guid.ID.ToString("N"));
GUILayout.Label("ST: " + guid.idString);
}
}
Some more info on why I need this.
This will be part of a system where I need to keep a player inventory/bag and know what prefab to spawn if he drops something form the bag. When a player pick up an item I simply save the GUID to the list of items in the bag while I remove the original GameObject from the world. I have a GameObject in the scene which carry a reference to all the item prefabs so that I can simply use that to find the prefab I want to instantiate. Later I need to expand on this idea to also work for a game save/load system and will have to generate unique IDs for objects in the scene too.
Every prefab copied somewhere is bound to either have a different name, time stamp or time stamped meta file produced by unity.
Is it not possible to combine your GUID along with an md5 hash of prefab name + time stamp information extracted from the prefab, meta file or perhaps both and use this as your new identifier?
Thinking about this, filename and path MD5’d should work too.
If i got your right you just need this at edit time to give each prefab a unique ID. In this case you can try using the “quite new” AssetModificationProcessor.
This works for me:
//C#
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
public class DetectDuplicates : AssetModificationProcessor
{
public static List<string> newAssets = new List<string>();
static void OnWillCreateAsset(string aMetaAssetPath)
{
string assetPath = aMetaAssetPath.Substring(0,aMetaAssetPath.Length-5);
newAssets.Add(assetPath);
}
}
class DetectDuplicatesPostprocessor : AssetPostprocessor
{
static void OnPostprocessAllAssets(string[] importedAssets,string[] deletedAssets,string[] movedAssets,string[] movedFromAssetPaths)
{
if (DetectDuplicates.newAssets.Count == 0)
return;
foreach (var str in importedAssets)
{
if (DetectDuplicates.newAssets.Contains(str))
{
GameObject obj = AssetDatabase.LoadAssetAtPath(str,typeof(GameObject)) as GameObject;
if (obj == null)
continue;
var comp = obj.GetComponent<YourPrefabComponent>();
if (comp == null)
continue;
comp.GenerateNewPrefabID();
}
}
DetectDuplicates.newAssets.Clear();
}
}
In my sample the component attached to the prefab is named “YourPrefabComponent” and it has a public function called GenerateNewPrefabID. This Postprocessor will execute this function if the asset it newly created.
How it works:
The AssetModificationProcessor gets informed when Unity will create a new meta file (for a new asset). I just strip the .meta and save the filename as “new asset” in a List.
When the asset is finally created and imported the AssetPostprocessor will take care of “postprocessing” the actual asset if it’s in the list.