Skip to content

Instantly share code, notes, and snippets.

@andrievsky
Last active February 12, 2019 10:08
Show Gist options
  • Save andrievsky/19186d13acefe0a2acad8b65d59d5061 to your computer and use it in GitHub Desktop.
Save andrievsky/19186d13acefe0a2acad8b65d59d5061 to your computer and use it in GitHub Desktop.
Serialize asset string uri instead of Unity reference to decouple assets from each other and improve loading performance.
using System;
using UnityEngine;
using Object = UnityEngine.Object;
#if UNITY_EDITOR
using UnityEditor;
#endif
/**
* Usage
*
* // Bind in default way
* [AssetUri(typeof(Sprite))] public string SpriteUri;
*
* // Bind in custom way
* SpriteUri = (Sprite) AssetUriDrawer.Field("Select Sprite", SpriteUri, typeof(Sprite));
*
* // Load resource at runtime
* void Start() {
* var sprite = AssetUriLoader.Load<Sprite>(SpriteUri);
* }
*/
public class AssetUri : PropertyAttribute
{
public readonly Type Type;
public AssetUri(Type type)
{
Type = type ?? typeof(Object);
}
}
public static class AssetUriLoader
{
public const string DefaultResourcesPath = "Assets/Resources/";
public static T Load<T>(string uri) where T : Object
{
return Resources.Load<T>(uri);
}
public static Object Load(string uri)
{
return Resources.Load(uri);
}
}
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(AssetUri))]
public class AssetUriDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
if (property.propertyType != SerializedPropertyType.String)
{
EditorGUI.LabelField(position, label.text, "Use AssetUri with string.");
return;
}
var attr = attribute as AssetUri;
var uri = property.stringValue;
Object value = null;
if (!string.IsNullOrEmpty(uri))
{
value = AssetUriLoader.Load(uri);
}
property.stringValue = Resolve(EditorGUI.ObjectField(position, value, attr.Type, false));
}
public static string Field(string label, string uri, Type type)
{
Object value = null;
if (!string.IsNullOrEmpty(uri))
{
value = AssetUriLoader.Load(uri);
}
return Resolve(EditorGUILayout.ObjectField(label, value, type, false));
}
public static string Resolve(Object value)
{
if (value == null)
{
return null;
}
var assetPath = AssetDatabase.GetAssetPath(value);
if (string.IsNullOrEmpty(assetPath))
{
return null;
}
if (!assetPath.Contains(AssetUriLoader.DefaultResourcesPath))
{
throw new ArgumentException("Asset should be in " + AssetUriLoader.DefaultResourcesPath);
}
var startIndex = AssetUriLoader.DefaultResourcesPath.Length;
var endIndex = assetPath.LastIndexOf('.');
if (endIndex == -1)
{
throw new ArgumentException("Asset file name should ends with .*");
}
return assetPath.Substring(startIndex, endIndex - startIndex);
}
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment