Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

how to keep reference to the original asset?

Discussion in 'Scripting' started by laurentlavigne, Jan 10, 2018.

  1. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    5,987
    Code (CSharp):
    1. public class Item : MonoBehaviour
    2. {
    3.     public GameObject prefab;
    4. }
    A prefab P has this script attached to it.
    prefab variable is set to the prefab itself.
    When the prefab is instantiated in the scene, prefab now points to the instance and not the prefab.
    Is there a way to have it still point to the prefab?
    I remember some convoluted way to do this, it used OnSerialize and stored the asset path to a string but maybe there is a simpler way to do this now.
     
  2. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    How do you instantiate it?
    If I was looking to do what you're saying, I might have:
    Code (csharp):
    1.  
    2. public class Script1 : MonoBehaviour {
    3. public GameObject prefab;
    4.  
    5. void Update() {
    6.    if (Input.GetKeyDown(KeyCode.N)) {
    7.       Item newitem = Instantiate(prefab) as Item;
    8.    // if for any reason that line of code above is invalid, then just make it a game object
    9.    // and the next line, GetComponent<Item> etc..
    10.       newitem.prefab = prefab;
    11.       }
    12.    }
    13. }
    14.  
     
  3. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    5,987
    Some time I drag and drop it in the scene.
     
  4. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Sure, well if you drag n drop it in the scene, and it has the reference to itself then.. simply drag n drop the prefab to the newly made scene item?
     
  5. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    5,987
    times 100 ;)
     
  6. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    duplicate? lol I don't know
     
  7. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    5,987
    this is what I had to do for scene fields... when I see this, I'm so tempted to procrastinate
    Code (CSharp):
    1. using UnityEngine;
    2. #if UNITY_EDITOR
    3. using UnityEditor;
    4. #endif
    5. [System.Serializable]
    6. public class SceneField
    7. #if UNITY_EDITOR
    8.     : ISerializationCallbackReceiver
    9. #endif
    10. {
    11.     #if UNITY_EDITOR
    12.     public void OnBeforeSerialize ()
    13.     {
    14.         m_scenePath = AssetDatabase.GUIDToAssetPath(m_GUID);
    15.     }
    16.     public void OnAfterDeserialize ()
    17.     {
    18.     }
    19.     #endif
    20.  
    21.     [SerializeField]
    22.     Object m_SceneAsset;
    23.     [SerializeField]
    24.     string m_GUID;
    25.     [SerializeField]
    26.     string m_scenePath;
    27.     public string path
    28.     {
    29.         get{return m_scenePath;}
    30.     }
    31. }
    32.  
    33. #if UNITY_EDITOR
    34. [CustomPropertyDrawer(typeof(SceneField))]
    35. public class SceneFieldPropertyDrawer : PropertyDrawer
    36. {
    37.     public override void OnGUI(Rect _position, SerializedProperty _property, GUIContent _label)
    38.     {
    39.         EditorGUI.BeginProperty(_position, GUIContent.none, _property);
    40.         SerializedProperty sceneAsset = _property.FindPropertyRelative("m_SceneAsset");
    41.         SerializedProperty sceneGUID = _property.FindPropertyRelative("m_GUID");
    42.         _position = EditorGUI.PrefixLabel(_position, GUIUtility.GetControlID(FocusType.Passive), _label);
    43.         if (sceneAsset != null)
    44.         {
    45.             sceneAsset.objectReferenceValue = EditorGUI.ObjectField(_position, sceneAsset.objectReferenceValue, typeof(SceneAsset), false);
    46.             if( sceneAsset.objectReferenceValue != null )
    47.             {
    48.                 sceneGUID.stringValue = AssetDatabase.AssetPathToGUID (AssetDatabase.GetAssetPath ((sceneAsset.objectReferenceValue as SceneAsset)));
    49.             }
    50.         }
    51.         EditorGUI.EndProperty( );
    52.     }
    53. }
    54. #endif
     
  8. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    5,987
    with a gameobject i'd use some asset load thing, plop them all inside resources folder like the old days and call Resource.Load()
    but no, I'll just do an intermediate thing with scriptable object... oh lord have mercy
     
  9. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Ya, I had to leave for a bit. Resources.Load or a SO with a reference were the 2 things I was going to suggest :)
     
  10. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Cheat and use an intermediary GameObject.

    You can do this two ways.
    1. Create a GameObject in the scene. Set up the correct references. Use that to do all Instantiation.
    2. Create a new prefab or scriptable object. Use that as a layer of indirection to get the right reference.
    Or just reassign the reference after instantiating the object.