1
\$\begingroup\$

I'm working on a UI system that animates an element's properties using coroutines. Every element that should be animated has a component called AnimatedUIElement which provides the function Enter().
The function Enter() is basically starting coroutines depending on the chosen animation settings, but only after calling Enable(), which sets the gameObject active with gameObject.SetActive(true);, updates its component references and makes the element interactable. AnimatedUIElement also defines an Exit() function acting similar, but disabling the element after the animation.

public class AnimatedUIElement : MonoBehaviour {
    private CanvasGroup canvasGroup;
    // ...

    public void Enter() {
        // ...
        TriggerEntry();
    }

    private void TriggerEntry() {
        PlayChildrenEntry(); // Calls Enter() on all animated Children
        Enable();
        StartCoroutine(SomeAnimation(...));
    }

    private void Enable() {
        gameObject.SetActive(true);
        Init();
        canvasGroup.interactable = true;
        canvasGroup.blocksRaycasts = true;
    }

    private void Init() {
        canvasGroup = GetComponent<CanvasGroup>();
        // ...
    }

    private IEnumerator SomeAnimation(...) { ... }

    public void Exit() {
        // Similar to Enter, but disabling the element
    }
}

Now I want to open the options panel by clicking a button in the game's UI. The panel is inactive (unticked) in the beginning, while the AnimatedUIElement component is enabled.

UI Hierarchy Screenshot
UI Hierarchy: Options Button calls Enter() on Options Panel.

<code>OnClick</code> Events of the Options Button
The desired setup in the Button Component calling OptionsPanel.Enter() and MainPanel.Exit()


But clicking the button throws the following exception:

Coroutine couldn't be started because the the game object 'Main Menu Button' is inactive!
UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
AnimatedUIElement:AnimatePosition(Vector2, Vector2, Single, AnimationCurve) (at Assets/Animated UI Elements/AnimatedUIElement.cs:265)
AnimatedUIElement:TriggerEntry() (at Assets/Animated UI Elements/AnimatedUIElement.cs:93)
AnimatedUIElement:Enter() (at Assets/Animated UI Elements/AnimatedUIElement.cs:73)
AnimatedUIElement:PlayChildrenEntry(Transform) (at Assets/Animated UI Elements/AnimatedUIElement.cs:219)
AnimatedUIElement:TriggerEntry() (at Assets/Animated UI Elements/AnimatedUIElement.cs:79)
AnimatedUIElement:Enter() (at Assets/Animated UI Elements/AnimatedUIElement.cs:73)
UnityEngine.EventSystems.EventSystem:Update()

In this stack trace you can see that the Options Panel did not start coroutines as no animation was defined in its component, but called Enter() on its children, which are animated.

Using debug logs I found out that, while Init() is called immediately after Enter(), Awake() is called after the coroutines (which happen later in the program flow) throw errors. This makes it seem like the object is not available instantly after calling setActive(true).

Is there an explanation and possibly a fix for this behavior?

\$\endgroup\$
  • \$\begingroup\$ try first setting the gameobject active, then when you call the button event it should work. another option would be to call that button event from a different active gameobject if that one has to be disabled until you hit the button. \$\endgroup\$ – Justin Markwell Feb 24 at 18:24
  • \$\begingroup\$ The object is disabled from the beginning and should not be active until explicitly requested by the user (via a button click), so I don't want to activate all objects at the start. The coroutine is setting values like position and alpha of the animated object. I would prefer that being done inside of the animated object itself. Also, when the values are animated, the object should be active already, so the whole animation is visible. I just don't know why it isn't. \$\endgroup\$ – Cebbi Feb 24 at 20:13
  • \$\begingroup\$ you could comment the enable code out and drag the OptionsPanel into the Options button event slot then select Gameobject/Active to true. \$\endgroup\$ – Justin Markwell Feb 25 at 3:35
  • \$\begingroup\$ @JustinMarkwell I just tried that, but the coroutines still throw the same exceptions. \$\endgroup\$ – Cebbi Feb 25 at 7:22
  • \$\begingroup\$ looks like somehow you are trying to call a button event from a object that is disabled at the time you call it. I am not sure how you have it setup but you must call it when it is active in hierarchy is there another animation playing that disables the object via animation? if so call a rebind to the animator to reset it before you play the next anim. \$\endgroup\$ – Justin Markwell Feb 25 at 14:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.