Search Unity

ScriptableObjects and storing Array of Transforms

Discussion in 'Scripting' started by Thewerebean, Sep 17, 2018.

  1. Thewerebean

    Thewerebean

    Joined:
    Jan 28, 2016
    Posts:
    21
    Hello,

    I am trying to use ScriptableObjects to store the Transforms of GameObjects in an Array in order to 'create' the next tevel.

    My plan was to drag and drop the positions of theses GameObjects in the editor for the ScriptableObject to Store the Transform at this moment in Array, just the values at moment t.

    After that, another Script would 'load' this SO and Instantiate all the GameObject in these positions.

    But it seems I can't drag and drop GameObjects in the scene in the SO. I understand this is not an active asset but why can't it store the value of the transform at this moment?

    Thanks,

    Edit : Here I'm storing those datas with Vector3 manually, one by one, but that's not ideal!
     
    Last edited: Sep 17, 2018
  2. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,282
    It can store the values but if you have a SO which has a Transform or Gameobject field then dragging it onto that slot is not asking it to save the data, it's asking it to save a reference to the instance. A project asset can not reference a scene asset. If you just want the data then instead of having a Transform field, have a Vector field(like you say) and write a custom editor that lets you drop a Transform in and automatically pulls the required data out for you, so you don't need to manually enter it.
     
  3. Thewerebean

    Thewerebean

    Joined:
    Jan 28, 2016
    Posts:
    21
    Thank your for your response, I wrote a little custom editor tool that works perfeclty fine, thank you!
     
    karl_jones likes this.
  4. dARTillery

    dARTillery

    Joined:
    May 14, 2020
    Posts:
    7
    Resurrecting this old post, I have the same problem and I tried to write this editor script but couldn't. any help would be appreciated.
     
    Last edited: Jun 8, 2022
  5. mikeohc

    mikeohc

    Joined:
    Jul 1, 2020
    Posts:
    215
    One easier way to do this without having to create a custom editor is to write a script that takes a scriptable object and an array of gameobjects.

    Code (CSharp):
    1.  
    2. [SerializeField] ScriptableObject _objectToChange;
    3. [SerializeField] Vector3[] storedPositions;
    4. [SerializeField] GameObject[] _gameObjectsRef;
    5.  
    6. [ContextMenu("Store GameObjects Positions for SO")]
    7.     void StoreGameObjectPositionsIntoSO()
    8.     {
    9.         if (_gameObjectsRef.Length > 0)
    10.         {
    11.             System.Reflection.FieldInfo _positions = _objectToChange.GetType().GetField("_positions");
    12.             storedPositions = new Vector3[_gameObjectsRef.Length];
    13.  
    14.             for (int i = 0; i < _gameObjectsRef.Length; i++)
    15.             {
    16.                 storedPositions[i] = _gameObjectsRef[i].transform.position;
    17.  
    18.             }
    19.  
    20.             if (_positions != null)
    21.             {
    22.                 _objectToChange.GetType().GetField("_positions").SetValue(_objectToChange, storedPositions);
    23.             }
    24.             else
    25.             {
    26.                 Debug.Log("_positions variable does not exist in this SO : " + _objectToChange.name);
    27.             }
    28.         }
    29.     }
    The code above uses all the gameobject referenced in the inspector to get an array of vector3 positions. Then it searches for the field "_positions" in the SO. If the field exists, we set the field to storedPositions.

    Make sure that matches the field name you set in your own SO. Maybe use properties instead of field but not sure if it's that important in this case.

    Attach this to any gameobject in the scene, and click on the context menu (three dots) from the script.