Search Unity

AddComponent going to queue if called from Start

Discussion in 'Scripting' started by jordidalmaucolell2, Jun 19, 2019.

  1. jordidalmaucolell2

    jordidalmaucolell2

    Joined:
    Jun 10, 2019
    Posts:
    1
    I've been noticed after long hours of pain, that if I call gameObject.AddComponent<Mytype>() from a Start method, it returns null and the component is added later.
    Is there any way to avoid this queueing?

    <<More detailed explanation of my project here>>
    Maybe I am doing my program in the wrong way and this problem is caused by a wrong design.

    What I want to do is, instead having a long if chain for the controls, have this controls separated in diferent components. For example Movement, Combat, Dialog, Minigame1, Minigame2, etc...



    This components extend from a class named ControlConfiguration, that will provide some basic utilities for the childs. You can see the lines that are giving me problems in Start(). If the ControlManager I will show you later is not already added in the gameObject, add it, but it returns null.
    RunActionIfKeyPressed , as the name says, runs the action you give if some of the array keys you give is pressed.

    Code (CSharp):
    1. [System.Serializable]
    2. public class ControlConfiguration : MonoBehaviour
    3. {
    4.  
    5.     protected ControlManager manager;
    6.  
    7.     void Start()
    8.     {
    9.         manager = gameObject.GetComponent<ControlManager>();
    10.         if (!manager)
    11.         {
    12.             manager = gameObject.AddComponent<ControlManager>();
    13.         }
    14.         manager.Configurations.Add(this);
    15.     }
    16.  
    17.     public void RunOn(GameObject gameObject)
    18.     {
    19.  
    20.     }
    21.  
    22.     public void RunActionIfKeyPressed(KeyCode[] keys, Action action)
    23.     {
    24.         foreach(KeyCode key in keys)
    25.         {
    26.             if(Input.GetKey(key))
    27.             {
    28.                 action();
    29.                 break;
    30.             }
    31.         }
    32.     }
    33.  
    34. }
    Here it goes the code of one extension of ControlConfiguration. As you can see, using RunActionIfKeyPressed we avoid the if chains i talk about above. RunOn is declared in ControlConfiguration, and provides the GameObject where we will apply the changes.

    Code (CSharp):
    1. [System.Serializable]
    2. public class MovementConfiguration : ControlConfiguration
    3. {
    4.  
    5.     public float Speed;
    6.     public float JumpSpeed;
    7.  
    8.     public KeyCode[] Left;
    9.     public KeyCode[] Right;
    10.  
    11.     public KeyCode[] Up;
    12.     public KeyCode[] Down;
    13.  
    14.     public KeyCode[] Jump;
    15.  
    16.     void RunOn(GameObject gameObject)
    17.     {
    18.         var tr = gameObject.transform;
    19.         var rb = gameObject.GetComponent<Rigidbody2D>();
    20.         var spriteRenderer = gameObject.GetComponent<SpriteRenderer>();
    21.  
    22.         this.RunActionIfKeyPressed(Left, () => {
    23.             rb.velocity = tr.forward * -Speed;
    24.             spriteRenderer.flipX = true;
    25.         });
    26.  
    27.         this.RunActionIfKeyPressed(Right, () => {
    28.             rb.velocity = tr.forward * Speed;
    29.             spriteRenderer.flipX = false;
    30.         });
    31.  
    32.     }
    33. }
    And this is the little code that makes all this run. This class is important because later it will provide access to some utilities to manage the current ControlConfigurations in the game.

    Code (CSharp):
    1. public class ControlManager : MonoBehaviour
    2. {
    3.     // This will be changed for a dictionary <ControlConfiguration, GameObject>
    4.     public List<ControlConfiguration> Configurations;
    5.  
    6.     void FixedUpdate()
    7.     {
    8.         foreach(ControlConfiguration configuration in Configurations)
    9.         {
    10.             // Will provide the GameObject corresponding to each ControlConfiguration
    11.             configuration.RunOn(gameObject);
    12.         }
    13.     }
    14.  
    15. }
    As you can see, using this system I get some advantages:
    1. Avoid long if chains
    2. Replaceable controllers
    3. Inspector configurable keys for controller actions
    4. In a future, a lot of facilities to manage the controllers fron the ControlManager
    <<Thanks for reading this question :), I hope you can help me a bit with this little issue im trying to deal with>>

    Have a nice day!
     

    Attached Files:

  2. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    AddComponent isn't delayed and shouldn't be returning null unless it fails for other reasons.

    Are you sure the issue isn't that your functions are private and / or aren't marked virtual, so the child classes aren't executing them?