You can’t create references to objects from the AssetDatabase on runtime. Then only exception are Resource assets.
The main reason is, that Unity builds exclude all non-referenced assets. So there must be a known web of references to difrerent assets at runtime. The FIleID and the way how unity assets serialize references is nothing you can affect or re-use.
You can, however, serialize ‘references’ to the Resources object, by serializing its path and type. And you can easily create custom serialized struct that holds these values inside and does the Resources.Load for you. You an even create editor drawers to make the inspector for this struct look like an object field.
Here’s my Resource struct
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Framework
{
[System.Serializable]
[Serialization.Serializable]
public struct Resource : Serialization.ISerializationCallbackReceiver, ISerializationCallbackReceiver
{
public static Resource empty
{
get { return new Resource(); }
}
[System.Serializable]
[Serialization.Serializable]
public struct Address
{
public Address(string _uri, System.Type _type)
{
uri = _uri;
typeName = TypeToString.GetTypeName(_type);
}
public static bool operator ==(Address lhs, Address rhs)
{
return Equals(lhs, rhs);
}
public static bool operator !=(Address lhs, Address rhs)
{
return !Equals(lhs, rhs);
}
public static bool Equals(Address lhs, Address rhs)
{
return lhs.uri == rhs.uri && lhs.typeName == rhs.typeName;
}
public override int GetHashCode()
{
return uri.GetHashCode() ^ typeName.GetHashCode();
}
public override bool Equals(object obj)
{
if (obj is Address)
{
var other = (Address)obj;
return Equals(this, other);
}
return false;
}
[Serialization.SaveAsValue, SerializeField] public string uri;
[Serialization.SaveAsValue, SerializeField] public string typeName;
}
public static bool Equals(Resource lhs, Resource rhs)
{
return Address.Equals(rhs.address, lhs.address);
}
public static bool operator ==(Resource lhs, Resource rhs)
{
return lhs.address == rhs.address;
}
public static bool operator !=(Resource lhs, Resource rhs)
{
return lhs.address != rhs.address;
}
public override int GetHashCode()
{
return address.GetHashCode();
}
public override bool Equals(object obj)
{
if (obj is Resource)
{
var other = (Resource)obj;
return Equals(this, other);
}
return false;
}
public Resource(Address address) : this()
{
m_address = address;
m_dirty = true;
}
public void SetDirty()
{
m_dirty = true;
}
private UnityEngine.Object m_obj;
[SerializeField][Serialization.SaveAsValue] private Address m_address;
private bool m_dirty;
public Address address
{ get { return m_address; } }
public UnityEngine.Object obj
{
get
{
if ( m_dirty )
{
m_dirty = false;
try
{
var type = TypeToString.ParseType(m_address.typeName);
// a hotfix for the new namespace
if(type == null)
type = TypeToString.ParseType("GrayZone."+m_address.typeName);
m_obj = Resources.Load(m_address.uri, type);
}
catch
{
m_obj = null;
}
}
return m_obj;
}
}
public void OnBeforeSerialize()
{
}
public void OnAfterDeserialize()
{
m_dirty = true;
}
#if UNITY_EDITOR
public static Address Editor_GetObjectAddress(Object obj)
{
Address address = new Address();
if (obj)
{
var assetPath = UnityEditor.AssetDatabase.GetAssetPath(obj);
var split = assetPath.Split(System.IO.Path.PathSeparator, System.IO.Path.AltDirectorySeparatorChar);
var newPath = "";
var resFound = false;
for (int i = split.Length - 1; i >= 0; --i)
{
var part = split*.ToLower();*
if (part == “resources”)
{
resFound = true;
break;
}
newPath = System.IO.Path.Combine(part, newPath);
}
if (resFound)
{
newPath = System.IO.Path.ChangeExtension(newPath, null);
address.typeName = TypeToString.GetTypeName(obj.GetType());
address.uri = newPath;
}
else
{
address.typeName = null;
address.uri = “”;
}
}
else
{
address.uri = “”;
address.typeName = null;
}
return address;
}
#endif
}
}
And the drawer
using UnityEditor;
using UnityEngine;
using System.Collections.Generic;
using System.Reflection;
namespace Framework.Editor
{
[CustomPropertyDrawer(typeof(Resource))]
[CustomPropertyDrawer(typeof(ResourceAttribute))]
public class ResourceDrawer : PropertyDrawer
{
public System.Type GetResourceType()
{
var attrib = attribute as ResourceAttribute;
var resType = attrib != null ? attrib.resourceType : typeof(Object);
return resType;
}
public override void OnGUI( Rect position, SerializedProperty property, GUIContent label )
{
//var objProperty = property.FindPropertyRelative(“m_obj”);
//EditorGUI.PropertyField(position, objProperty, label, true);
var names = property.propertyPath.Split(‘.’);
var targets = property.serializedObject.targetObjects;
var results = new List();
EditorReflectionUtility.GetVariable(names, targets, results);
Object obj = results[0].obj;
for ( int i = 1; i < results.Count; ++i )
{
var otherObj = results*.obj;*
if ( otherObj != obj )
{
EditorGUI.showMixedValue = true;
break;
}
}
EditorGUI.BeginChangeCheck();
GUI.backgroundColor = new Color(0.9f,0.9f,1f,1f);
var newObject = EditorGUI.ObjectField(position, label, obj, GetResourceType(), false);
GUI.backgroundColor = Color.white;
if ( EditorGUI.EndChangeCheck() )
{
Undo.RecordObjects(targets, “Setting Resource”);
var newRes = new Resource(Resource.Editor_GetObjectAddress(newObject));
newRes.SetDirty();
EditorReflectionUtility.SetVariable(names, targets, newRes);
foreach ( var targ in targets )
{
EditorUtility.SetDirty(targ);
var onValidate = targ.GetType().GetMethod(“OnValidate”, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
if ( onValidate != null)
onValidate.Invoke(targ, null);
}
}
EditorGUI.showMixedValue = false;
return;
}
}
}
Just as an example, not all code dependencies are included