Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Adding GameObject to a list/Array in inspector by a EditorWindow script

Discussion in 'Immediate Mode GUI (IMGUI)' started by Anraksha, Jul 4, 2017.

  1. Anraksha

    Anraksha

    Joined:
    Dec 9, 2016
    Posts:
    10
    Hello,

    All that will folow where done on Unity 5.6.1f1;

    I'm currently on a EditorWindow creation and i have a button which create a gameobject with some script attached to it and I add it to a list/array which is in an other script.

    When created the object appear clearly in the list without problem and the list/array grow well each time I add an object.

    But when I go to play mode all modification made by script disappear from the list and it return to it's original form. The only way i found to keep the change is to add manually by drag and drop an object at the end of the list when i have finished creating all object I need.

    Is there a way to keep the change made by script without drag and droping ? To save the new current state of the list/array.

    I have already tested :
    • recreating the array/list.
    • resizing the list and adding at the last index the object.
    • just add the object
    • creating a new list/array put in it the old list/array adding the new value and set the old list to the new list
    But neither of all that worked.

    Is there a way to do that or is this impossible.



    Cordially,
    Anraksha
     
  2. PsyKaw

    PsyKaw

    Joined:
    Aug 16, 2012
    Posts:
    102
    Can u post some code ? I think if your list is serialized with your editor window, it should be ok.
     
  3. Anraksha

    Anraksha

    Joined:
    Dec 9, 2016
    Posts:
    10
    Hi,

    I'm quite new to unity and C# so I can't if it's serialized but :

    here is the array ( my last try) which is in a script i use to spawn the avatar.
    Code (CSharp):
    1.    
    2.     [SerializeField]
    3.     public AvatarExposer[] avatarU;
    4.  
    and here the insertion which is done in a Editor Window Extension.

    Code (CSharp):
    1. var ii = PoolOrigin.GetComponent<AvatarPoolScript>().avatarU.Length;
    2.                 var u = PoolOrigin.GetComponent<AvatarPoolScript>().avatarU;
    3.                 var c = new AvatarExposer[ii + 1];
    4.  
    5.                 u.CopyTo(c, 0);
    6.                 c[ii] = _3rdPerson.GetComponent<AvatarExposer>();
    7.  
    8.                 PoolOrigin.GetComponent<AvatarPoolScript>().avatarU = c;

    when click on the button which do the code above at first sight it add well the component to the list but when i play it all the modification disapear.

    And like i said in my first post the only way i found to keep the change is to add one more component to the list/array manually.
     
  4. PsyKaw

    PsyKaw

    Joined:
    Aug 16, 2012
    Posts:
    102
    Can you post all the code of AvatarExposer to see if it's well serialized. (but i think the problem is not here)

    I don't understand very weel what you are trying to do in your editor code.

    First if you array is often resized you should use List instead of array:
    Code (csharp):
    1. using System.Collections.Generic;
    2.  
    3. [SerializeField]
    4. public List<AvatarExposer> avatarU;
    So it's very simple to add a new element to the list:
    Code (csharp):
    1. avatarU.Add(_3rdPerson.GetComponent<AvatarExposer>())
    For more help i need entire code of your Editor Window. Above all need to see how you get PoolOrigin.
     
    Last edited: Jul 5, 2017
  5. Anraksha

    Anraksha

    Joined:
    Dec 9, 2016
    Posts:
    10
    Well like i said i already try it with a list but since it didn't work well i made some search on the internet and I have seen a post in which they said to used array so i tried but it didn't change anything

    Visual of the Editor Extension window the red part is due to confidentiality but is a preview of the avatar.




    the definition of all variable which gonna be used

    Code (CSharp):
    1. using Boo.Lang;
    2. using Invector;
    3. using Invector.CharacterController;
    4. using System.IO;
    5. using UnityEditor;
    6. using UnityEngine;
    7. using UnityEngine.EventSystems;
    8. using UnityEngine.UI;
    9.  
    10.   GUISkin skin;
    11.     GameObject charObj;
    12.     Animator charAnimator;
    13.     RuntimeAnimatorController controller;
    14.     v3rdPersonCameraListData cameraListData;
    15.     Vector2 rect = new Vector2(500, 630);
    16.     Vector2 scrool;
    17.     Editor humanoidpreview;
    18.     List<CharacterTemplate> templates;
    19.     List<string> templateNames;
    20.     int selectedTemplate=1;
    21.     CharacterTemplate currentTemplate;
    22.     Rect buttomRect = new Rect();
    23.  
    24.     GameObject PoolOrigin;
    25.     AvatarSpawner AVS;
    26.     string str="ExensAI";
    In the OnGUI part of the code
    Code (CSharp):
    1.         charObj = EditorGUILayout.ObjectField("FBX Model", charObj, typeof(GameObject), true, GUILayout.ExpandWidth(true)) as GameObject;
    2.  
    3.         if (GUI.changed && charObj != null)
    4.             humanoidpreview = Editor.CreateEditor(charObj);
    5.  
    6.         controller = EditorGUILayout.ObjectField("Animator Controller: ", controller, typeof(RuntimeAnimatorController), false) as RuntimeAnimatorController;
    7.  
    8.        
    9.         PoolOrigin = EditorGUILayout.ObjectField("Pool Origin", PoolOrigin, typeof(GameObject), true, GUILayout.ExpandWidth(true)) as GameObject;
    10.         AVS = EditorGUILayout.ObjectField("Spawn Point Origin", AVS, typeof(AvatarSpawner), true, GUILayout.ExpandWidth(true)) as AvatarSpawner;
    Here the code of the create function which is used by the button.

    Code (CSharp):
    1.     void Create()
    2.     {
    3.         // base for the character
    4.         var _3rdPerson = GameObject.Instantiate(charObj, Vector3.zero, Quaternion.identity) as GameObject;
    5.         if (!_3rdPerson)
    6.             return;
    7.         var rigidbody = _3rdPerson.AddComponent<Rigidbody>();
    8.         var collider = _3rdPerson.AddComponent<CapsuleCollider>();
    9.  
    10.         if (charType == CharacterType.CharacterController)
    11.         {
    12. [INDENT][INDENT]/// Invector Code ( I  erase it  cause i dont think invector would be happy :/[/INDENT][/INDENT]
    13.          }
    14.        
    15.         else if (charType == CharacterType.ExsensAI)
    16.         {
    17.             _3rdPerson.tag = "CompanionAI";
    18.             _3rdPerson.name = str;
    19.             if (EditorApplication.isPlaying) _3rdPerson.SetActive(false);
    20.             _3rdPerson.AddComponent<AvatarPatrolScript>();
    21.             _3rdPerson.AddComponent<AvatarExposer>();
    22.             _3rdPerson.AddComponent<AvatarScript>();
    23.             var sensor = new GameObject("AI_Sensor", typeof(SphereCollider), typeof(v_AISphereSensor));
    24.             var layer = LayerMask.NameToLayer("Triggers");
    25.             sensor.layer = layer;
    26.             sensor.tag = "Weapon";
    27.             sensor.transform.parent = _3rdPerson.transform;
    28.             sensor.transform.localPosition = Vector3.zero;
    29.             sensor.transform.localEulerAngles = Vector3.zero;
    30.             sensor.GetComponent<SphereCollider>().isTrigger = true;
    31.             var navMesh = _3rdPerson.AddComponent<UnityEngine.AI.NavMeshAgent>();
    32.             navMesh.radius = 0.3f;
    33.             navMesh.speed = 0f;
    34.             navMesh.angularSpeed = 300f;
    35.             navMesh.acceleration = 4f;
    36.             navMesh.autoBraking = false;
    37.             navMesh.autoTraverseOffMeshLink = false;
    38.  
    39.             var e_layer = LayerMask.NameToLayer("CompanionAI");
    40.             _3rdPerson.layer = e_layer;
    41.             foreach (Transform t in _3rdPerson.transform.GetComponentsInChildren<Transform>())
    42.                 t.gameObject.layer = e_layer;
    43.  
    44.             var a_layer = LayerMask.NameToLayer("Action");
    45.             _3rdPerson.GetComponent<AvatarPatrolScript>().actionLayer = LayerMask.GetMask(LayerMask.LayerToName(a_layer));
    46.             _3rdPerson.GetComponent<AvatarPatrolScript>().actionRayDistance = 0.7f;
    47.             _3rdPerson.GetComponent<AvatarPatrolScript>().avExp = _3rdPerson.GetComponent<AvatarExposer>();
    48.             _3rdPerson.GetComponent<AvatarPatrolScript>().agressive = false;
    49.             _3rdPerson.GetComponent<AvatarPatrolScript>().randomAttackCount = false;
    50.             _3rdPerson.GetComponent<AvatarExposer>().avatarPatrolScript = _3rdPerson.GetComponent<AvatarPatrolScript>();
    51.             _3rdPerson.GetComponent<AvatarScript>().AvatarComponentExposer = _3rdPerson.GetComponent<AvatarExposer>();
    52.             _3rdPerson.GetComponent<AvatarScript>().AvatarTransform = _3rdPerson.GetComponent<Transform>();
    53.             _3rdPerson.GetComponent<AvatarExposer>().avatarRigidbody=_3rdPerson.GetComponent<Rigidbody>();
    54.             _3rdPerson.GetComponent<AvatarExposer>().avatarTransform= _3rdPerson.GetComponent<Transform>();
    55.             _3rdPerson.GetComponent<AvatarPatrolScript>().poolOrigin = PoolOrigin;
    56.             _3rdPerson.GetComponent<AvatarPatrolScript>().avPool = AVS.getpoolScript();
    57.             _3rdPerson.GetComponent<AvatarScript>().OnMustDispose = new AvatarComponentExposerUnityEvent();
    58.             _3rdPerson.GetComponent<AvatarScript>().OnMustDispose.RemoveAllListeners();
    59.             UnityEditor.Events.UnityEventTools.AddPersistentListener(_3rdPerson.GetComponent<AvatarScript>().OnMustDispose, PoolOrigin.GetComponent<AvatarPoolScript>().DisposeAvatar);
    60.             _3rdPerson.transform.parent = PoolOrigin.transform;
    61.  
    62.             if (EditorApplication.isPlaying)
    63.             {
    64.                 PoolOrigin.GetComponent<AvatarPoolScript>().AddAvatarU(_3rdPerson.GetComponent<AvatarExposer>());
    65.             } else
    66.             {
    67. [INDENT][INDENT]// this par was in the precedent code the array part[/INDENT][/INDENT]
    68.                 PoolOrigin.GetComponent<AvatarPoolScript>().avatarU.Add(_3rdPerson.GetComponent<AvatarExposer>());
    69.             }
    70.         }
     
  6. PsyKaw

    PsyKaw

    Joined:
    Aug 16, 2012
    Posts:
    102
    Some advices:
    - You should keep reference on your component that you add:
    Code (csharp):
    1.  
    2. var avatarPatrol = 3rdPerson.AddComponent<AvatarPatrolScript>();
    3. var avatarExposer = _3rdPerson.AddComponent<AvatarExposer>();
    4. var avatar = _3rdPerson.AddComponent<AvatarScript>();
    5.  
    Event if it's a editor script, GetComponent can cost much if there are a lot of components on your gameobject.

    To resolve your problem:
    • You must be sure that your list in AvatarPoolScript of AvatarExposer is public or has attribute [SerializeField], but if you see it in inspector it should be ok.
    Try something like this, instead of:
    Code (csharp):
    1. PoolOrigin.GetComponent<AvatarPoolScript>().avatarU.Add(_3rdPerson.GetComponent<AvatarExposer>());
    Code (csharp):
    1. var avatarExposer = _3rdPerson.GetComponent<AvatarExposer>();
    2.  
    3. var pool = PoolOrigin.GetComponent<AvatarPoolScript>();
    4. var poolSerialized = new SerializedObject(pool);
    5. var avatarUSerialized = poolSerialized.FindProperty("avatarU");
    6. var index = avatarUSerialized.arraySize;
    7. avatarUSerialized.InsertArrayElementAtIndex(index);
    8. var newElement = avatarUSerialized.GetArrayElementAtIndex(index);
    9. newElement.objectReferenceValue = avatarExposer;
    10. poolSerialized.ApplyModifiedProperties();
    You have to work on serialized objects(SerializedObject) and properties(SerializedProperty) to be sure it will stay in play mode when unity will deserialize your object.
     
    dauswectus likes this.
  7. Anraksha

    Anraksha

    Joined:
    Dec 9, 2016
    Posts:
    10

    OH MY PsyKaw
    It work perfectly.
    Thanks you very much I was on that since monday but i didn't know this way of doing you made me learn something very useful.

    For the getComponent I already know that but didn't put it immediately but i intended to change that when this problem will be resolved.

    Thanks to you I can now concentrate myself on the optimisation.

    I thanks you again, and hope you'll have a good day.

    Cordially,
    Anraksha
     
  8. PsyKaw

    PsyKaw

    Joined:
    Aug 16, 2012
    Posts:
    102
    Glad to help you :)