- Home /
What's the best way to store a reference to a script asset?
To clarify, at runtime I'm looking to create and add a script to an object based on what type the reference has. This functionality already exists in the form of MonoScript (ScriptReference/MonoScript.html). However MonoScript only works in the editor.
I've considered the following 2 approaches but they seem either inefficient or error prone:
Use string properties and call gameObject.AddComponent(myString)
Store script asset references as a TextAsset and then call gameObject.AddComponent(myTextAsset.name);
Option 2 might be ok but I don't want Unity to load up the whole script file just to get its name.
Is there a better way?
Answer by PAEvenson · Feb 12, 2013 at 12:21 AM
You can probably just use an object reference or component reference and use AddComponent. http://docs.unity3d.com/Documentation/ScriptReference/Object.html
http://docs.unity3d.com/Documentation/ScriptReference/Component.html
I can assign script asset references to an Object variable but it doesn't work for Component. Thanks!
Answer by numberkruncher · Feb 12, 2013 at 12:41 AM
Scripts are compiled into an assembly and so are all available at runtime. I do not know if the representative assets have to be loaded however.
I would just input the name of the script using a regular string variable.
If you are using Unity 4 then you can implement a custom property drawer and attribute to achieve drag & drop in the inspector:
Usage:
public class SomeBehaviour : MonoBehaviour {
[ScriptPicker]
public string myScriptName;
public void Foo() {
gameObject.AddComponent(myScriptName);
}
}
Attribute Implementation:
using UnityEngine;
public class ScriptPickerAttribute : PropertyAttribute {
}
Drawer Implementation:
using UnityEngine;
using UnityEditor;
[CustomPropertyDrawer(typeof(ScriptPickerAttribute))]
public class ScriptPickerPropertyDrawer : PropertyDrawer {
public override void OnGUI(Rect position, SerializedProperty prop, GUIContent) {
Rect rect;
int controlID = GUIUtility.GetControlID(FocusType.Passive);
int objectFieldWidth = 45;
// Detect drag & drop
CheckDragAndDrop(position, prop, controlID);
// Allow manual text entry
rect = new Rect(
position.x,
position.y,
position.width - objectFieldWidth - 2,
position.height
);
prop.stringValue = EditorGUI.TextField(
rect, label, prop.stringValue
);
// Allow drag & drop or selection from dialog
rect = new Rect(
position.xMax - objectFieldWidth,
position.y,
objectFieldWidth,
position.height
);
MonoScript script = (MonoScript)EditorGUI.ObjectField(
rect, null, typeof(MonoScript), false
);
if (script != null) {
prop.stringValue = script.name;
}
}
private void CheckDragAndDrop(Rect position, SerializedProperty prop, int controlID) {
Event e = Event.current;
EventType eventType = e.GetTypeForControl(controlID);
switch (eventType) {
case EventType.DragUpdated:
case EventType.DragPerform:
if (position.Contains(e.mousePosition)
&& DragAndDrop.objectReferences.Length == 1
&& DragAndDrop.objectReferences[0] is MonoScript)
{
if (eventType == EventType.DragUpdated) {
DragAndDrop.visualMode = DragAndDropVisualMode.Generic;
DragAndDrop.activeControlID = controlID;
}
else {
prop.stringValue = DragAndDrop.objectReferences[0].name;
DragAndDrop.AcceptDrag();
DragAndDrop.visualMode = DragAndDropVisualMode.None;
}
e.Use();
}
break;
}
}
}
Your answer
Follow this Question
Related Questions
Need help with a raycast 1 Answer
how can I create a variable to refer to any gameObject script with pragma strict 1 Answer
Selling content with this script (Animating Tiled texture) 2 Answers
Unity Keeps Giving Me Errors On My Scripts 1 Answer
(Yet another) Accessing array in another script - ref or copy? 1 Answer