Skip to main content
gamedev.net
🔒 Locked

Develop drop down lists

Started by davejones 17 replies 5.8k views
Original Post
davejones
davejones

I am developing a 2D UI in unity. I have developed a scroll-able list of buttons in which the buttons are intractable. What I am trying to achieve is to have a sub list of items for each button of the scroll able list. In essence, have buttons in the scroll able list that toggle a sub-list to being visible/hidden.


Upon clicking a button the sub-list should appear vertically below the button that was pressed. When the sub list appears the buttons below the sub list should move negative in the vertical axis so that the sub list doesn't get covered/overlayed by the other buttons that make up the scroll able list. I have broken down what I am trying to achieve below.

- Developing a 2D UI that has a scroll able list of buttons

- Each button toggles a sub list visible/hiddenn that drops down below the button pressed

- Upon the list dropping down the buttons below the sub list should move negatively in the vertical axis so that the sub list items are not covered/overlayed by the buttons below the one clicked/pressed.

I have attached 2 images that show part of what I have done so far. If you have any questions do please let me know.


sublist_q_img_2.PNG

sublist_q_img_1.PNG

gg1233
gg1233

If I understand correctly what you are developping, you should look at TreeView.

It's for the editor only, but I think it's the behavior you want to recreate.

Scouting Ninja
Scouting Ninja
6 hours ago, davejones said:

What I am trying to achieve is to have a sub list of items for each button of the scroll able list.

I wanted to make a tutorial for this but don't have the time. So I decided to just make a Unity asset for you, then look at what I did and adjust it for yourself.

6 hours ago, davejones said:

- Developing a 2D UI that has a scroll able list of buttons

Use the Unity scrolling rect.

6 hours ago, davejones said:

- Each button toggles a sub list visible/hiddenn that drops down below the button pressed

You are on the right path. The trick is to make the menus inside of the other menus. This is known as nested widgets.


6 hours ago, davejones said:

- Upon the list dropping down the buttons below the sub list should move negatively in the vertical axis so that the sub list items are not covered/overlayed by the buttons below the one clicked/pressed.

The part you are missing is the Layout component. These layout components allow you to organize menus and the like.

You will also want to animate the widgets and setup a state machine for them using Unity's animations.

SlideMenu.gif.c284709879d25f09197029018f7d8f20.gif


Here is the Unity file, just import as a custom Unity pack: SlidingSubMenus.unitypackage

Play around with it and remove components to see what does what.


davejones
davejones
13 hours ago, Scouting Ninja said:

I wanted to make a tutorial for this but don't have the time. So I decided to just make a Unity asset for you, then look at what I did and adjust it for yourself.

Use the Unity scrolling rect.

You are on the right path. The trick is to make the menus inside of the other menus. This is known as nested widgets.


The part you are missing is the Layout component. These layout components allow you to organize menus and the like.

You will also want to animate the widgets and setup a state machine for them using Unity's animations.

SlideMenu.gif.c284709879d25f09197029018f7d8f20.gif


Here is the Unity file, just import as a custom Unity pack: SlidingSubMenus.unitypackage

Play around with it and remove components to see what does what.


The custom package you have developed put me in the right direction and I thank you for that. I just changed the script you made and the animation key frames too. The changes I have made to the script can be seen in this quote.


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);
		}
	}
    

    /*public void BtnRollUp()
    {
        print(AniPlayer.GetInteger("MenuState"));
        if (AniPlayer.GetInteger("MenuState") == 1)
        {
            AniPlayer.SetInteger("MenuState", 0);
        }
    }*/

    // Use this for initialization
    void Start () {
        AniPlayer = this.GetComponent<Animator>();
    }
	
	// Update is called once per frame
	void Update () {
 
	}
}


Scouting Ninja
Scouting Ninja
3 hours ago, davejones said:

I just changed the script you made and the animation key frames too.

Good work, good to see you understand the script.

You can also remove:


[HideInInspector]
int State = 0;

I added that in by habit because often I manage the state using the script with large animations. This animation was short so I never used that part.

davejones
davejones
1 hour ago, Scouting Ninja said:

Good work, good to see you understand the script.

You can also remove:



[HideInInspector]
int State = 0;

I added that in by habit because often I manage the state using the script with large animations. This animation was short so I never used that part.

I am now looking into how I can make the customdropdown items more flexible in terms of their Delta.y values. I believe that so far the customdropdowns developed are a good starting point, however the next step would be to have each customdropdown have its own Size Delta.y value.


At the moment each customdropdown UI item has the same size Delta.y value as they (UI customdropdown items) are being animated by the same animator. The reason why I am working towards a different Delta.y value for each UI customdropdown item is because the content within each customdropdown is varied in terms of the Delta.y needed to accommodate the content.

I have listed below what I am working towards and any feedback would be much appreciated.

- Have specific Size Delta.y value for each customdropdown UI item

- Specific change in y value allows for the differing sizes to appear neater and more optimum.

- If customs drop down [0,1,2,3,4,5,6,7,] pressed set.delta.y value = desired y value..

Just realised each submenu has its own animator so I am looking at changing the delta.y value there.

Scouting Ninja
Scouting Ninja
41 minutes ago, davejones said:

however the next step would be to have each customdropdown have its own Size Delta.y value.

The way to do this would be to either tweak the animation using a script or to make every menu by hand.

If you are going to have only 4-5 menus then the hand approach is easy. Just make new menus using the UI "panel" objects. You will see I colored the panels brightly so that you can see how many was used and where.

Then make a animation state machine for each menu. Unity's animation player is light weight so there won't be perfomance problems with this approach. Unity 2018 also improved the performance of the UI animations.

davejones
davejones
16 hours ago, Scouting Ninja said:

The way to do this would be to either tweak the animation using a script or to make every menu by hand.

If you are going to have only 4-5 menus then the hand approach is easy. Just make new menus using the UI "panel" objects. You will see I colored the panels brightly so that you can see how many was used and where.

Then make a animation state machine for each menu. Unity's animation player is light weight so there won't be perfomance problems with this approach. Unity 2018 also improved the performance of the UI animations.

How would the animation be tweaked using a script? I ask because I have more than 8 menus so I am looking to find an optimum way.

Scouting Ninja
Scouting Ninja
On 7/27/2018 at 12:05 PM, davejones said:

How would the animation be tweaked using a script?

Let's say you are trying to animate "Anchored Position.x".

You can instead grab the "Anchored Position.x" value in a script by using getComponent<RectTransform>().Position.x Then you add it to a public float. Now you can adjust the public float using the script.


To do this you need to know some basic animation math, and have experience with Unity's components system.


davejones
davejones
On 7/28/2018 at 6:42 PM, Scouting Ninja said:

Let's say you are trying to animate "Anchored Position.x".

You can instead grab the "Anchored Position.x" value in a script by using getComponent<RectTransform>().Position.x Then you add it to a public float. Now you can adjust the public float using the script.


To do this you need to know some basic animation math, and have experience with Unity's components system.


I have stumbled across an issue with the CustomDropDown class. The issue is that after I press the button and the list dropsdown I set the DropDownlist invisible. When I than set the DropDownlist to be visible again and press the button the list doesn't fold up. I believe I have narrowed the problem down to being a case of the menustate variable resets itself when the GameObject has been set invisible/visible. I am trying to find a way to keep the dropdown delta y postion the same when I reset the list to visible.


I have posted the code I have done so far below.


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

public class CustomDropDown : MonoBehaviour {

    public GameObject SubMenu;
    [HideInInspector]
    public int State = 0;
    private bool boState1;
    private float aniTime; 
    Animator AniPlayer;

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


		else if  (AniPlayer.GetInteger("MenuState") == 1)
		{
			AniPlayer.SetInteger("MenuState", 0);
            boState1 = false;
		}
	}

    void Start () {
        AniPlayer = this.GetComponent<Animator>();
       
    }
	
	
	void Update () {
        if (boState1 == true)
        {
            AniPlayer.Play("step3_dropdownstatic", 1, 0f);
            AniPlayer.SetInteger("MenuState", 1);

        }

        else
        {
            AniPlayer.SetInteger("MenuState", 0);


        }
    }
}


davejones
davejones

Once the submenu has dropped down and the gameobject is from true to false and back to true the state machine doesn't work as it initially did.

Scouting Ninja
Scouting Ninja
1 hour ago, davejones said:

Once the submenu has dropped down and the gameobject is from true to false and back to true the state machine doesn't work as it initially did.

I animated the values, maybe changing something removed the animation?

I like using the animation for this kind of thing, because then I don't need to check when the animation is done. Instead the animation changes the values right before it stops playing. Moving from the Animation to a "idle" animation; also means the values don't reset when the animation is done.


Just check the original to see how it worked. If you still can't solve it I will try to help; unfortunately I am a little pressed for time at the moment.

davejones
davejones

I have tried numerous things but still can't seem to solve the issue. I have listed below in points what the issue is.

- 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 added a link to a video with the image. https://gfycat.com/SkinnyNegativeChuckwalla
davejones
davejones

   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>();
    }

The animation state machine has an int for the state but so too does the class. I am looking at how to keep the animator on the current state rather than resetting to idle on being re enabled.

davejones
davejones

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.

Scouting Ninja
Scouting Ninja
On 8/16/2018 at 12:53 PM, davejones said:

The animation state machine has an int for the state but so too does the class.

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.

Basically the Unity animations uses states as triggers, it is always checking the states to see if it can move to the next state. Also checking the animation state instead of the class state should have a very similar cost; because it is only a pointer.


In other words, you could just use the Unity animation states; no reason not to.

davejones
davejones
12 hours ago, Scouting Ninja said:

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.

Basically the Unity animations uses states as triggers, it is always checking the states to see if it can move to the next state. Also checking the animation state instead of the class state should have a very similar cost; because it is only a pointer.


In other words, you could just use the Unity animation states; no reason not to.

So is it a case of just using the animation states parameters such as the trigger parameter and controlling the parameter though a class?

Locuskidd
Locuskidd
2 hours ago, davejones said:

So is it a case of just using the animation states parameters such as the trigger parameter and controlling the parameter though a class?

I think you might of hit the nail on the hesd.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.