- 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