Drop down list issue

I have a UI drop down list that uses an animation state machine to drop down/fold up a submenu. The issue I am having is that when the list has been dropped down, and the GameObject is set inactive and than reactive the drop down doesn’t work like it did before the GameObject was set inactive.

I have listed below the issue in points

  • press UI button that plays drop down animation clip
  • press same UI button again and fold up animation clip is played
  • press UI button and drop down plays again
  • set GameObject active to false when the drop down clip has been played
  • Set GameObject to true whilst the list is dropped down
  • press button to try and fold up but doesn’t work like before GameObject was set to false.

I have attached the class used OnClick of the UI button below. I want the same behaviour that was apparent before the GameObject was set to false. The link is to a video that shows the issue. SkinnyNegativeChuckwalla

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CustomDropDown : MonoBehaviour {

    public GameObject SubMenu;
    [HideInInspector]
    public int State = 0;

    Animator AniPlayer;

    public void BtnDropDown()
    {
        if (AniPlayer.GetInteger("MenuState") == 0)
        {
            AniPlayer.SetInteger("MenuState", 1);
        }


        else if (AniPlayer.GetInteger("MenuState") == 1)
        {
            AniPlayer.SetInteger("MenuState", 0);
        }
    }
        // Use this for initialization
        void Start() {
            AniPlayer = this.GetComponent<Animator>();
        }

    }

From looking at your video, the animator is resetting after you re-enable it. The code you have above is taking the ‘menu state’ value from the animator.

There is already a “state” int in the code. Could you not use that instead- would that fix the problem? Something like this maybe :-

public class CustomDropDown : MonoBehaviour
{
    public int State { get; private set; }

    public void BtnDropDown()
    {
        State = 1 - State;
        m_aniPlayer.SetInteger("MenuState", State);
    }

    void Start()
    {
        State = 0;
        m_aniPlayer = this.GetComponent<Animator>();
    }

#pragma warning disable 649
    [SerializeField] GameObject SubMenu;
#pragma warning restore 649

    Animator m_aniPlayer;
}

I have tried this but the state machine seems to work the same as with the original code I have posted. When I disable/enable the GameObject the animator resets, rather than staying on the state it was in before it was disabled. Why is it you have added the pragma warning?

Do you need to add a link in the controller from the default entry point directly to the “opened” state, or does the state machine have to go through the “closed” state first?

I use it when dealing with values that will, or may, be set in the Editor. It keeps the compilation clean by preventing that particular warning. The warning suppression is restricted to only those lines with such variables (by disabling and then immediately restoring the warning) as it is generally advisable to not ignore warning messages.

I don’t want the state machine to go though the closed state first. I believe I want a link from the entry point to the opened state.

Thinking about it, you may want to add an OnEnable() that sets the value of State in the animator to correctly restore its value.

I have tried this but it didn’t manage to solve the problem.

Psuedocode

onEnable

menu state = current state

OnDisable

menu state = current state

I suppose its just a case of finding out how to do this because I believe the issue is that the animation state machine resets on disabling/ re enabling of the GameObject.

I agree. Try removing the OnDisable. There is no need for it if you are using code similar to that in post #2.

It is recommended to use the Unity animation state for this. Or you could just check that the animation state is always equal to the class state.

I am also looking into the state machines trigger parameter. The idea is that it is always checking the states to see if it can move to the next state. I am thinking of using the trigger parameter to check which state is currently being played and controlling this through a script.

I think that, as a general rule, you would want your code to be driving the animation (state machine) rather than the other way round. Note, this sentiment is driven more by my own personal opinion than any cold hard facts. :slight_smile:

If you really want to drive the code from the animation, you can do so using Animation Events.

However, in the case as stated above (I’m presuming here your animation sequence is, in fact, no more complicated than described), it would seem sufficient to drive the animation from the code. Simply set the trigger (I would use a trigger rather than an int) in code and have the animation act on that trigger. You should not need to read the trigger back as you would already know it directly from the code (in State as per my example in post #2).

The omission in my post #2 was that it was not writing the value of State back to the animator when being enabled (which I mentioned in post #6 which should work if the change described in post #5 is added).

1 Like