New UI - How to do a transition on cue?

After scouring the documentation, I haven’t figured out an obvious way to do a state transition for a UI element without user interaction of some sort.

For example, suppose I wanted to have a “Selectable” or “Button” do a transition to its “selected” state at any point in time. The user wouldn’t be mousing over the button, I’d just be calling a function like “button.doTransitionDown”, though such a function doesn’t seem to exist. What would be the best/easiest way to accomplish this?

1 Answer

1

You can inherit from the standalone input manager and then override the process function to add some of your own input management, something like the following should work:

using UnityEngine;
using UnityEngine.EventSystems;

public class MyInputModule : StandaloneInputModule {
	public GameObject m_TargetObject;
	public bool OnActionEvent1;
	public bool OnActionEvent2;
	
	void Update(){
		if(Input.GetKey(KeyCode.Q)){
			OnActionEvent2 = true;
		}
		if(Input.GetKeyUp(KeyCode.Q)){
			OnActionEvent2 = false;
		}
	}
	public override void Process(){
		base.Process();
		
		if (m_TargetObject == null){
			return;
		}
		if(OnActionEvent1 || OnActionEvent2){
			ExecuteEvents.Execute(m_TargetObject, new BaseEventData(eventSystem), ExecuteEvents.selectHandler);
		}else{
			ExecuteEvents.Execute(m_TargetObject, new BaseEventData(eventSystem), ExecuteEvents.deselectHandler);
		}
	}
	public void OnEnterEvent(BaseEventData eventData){
		OnActionEvent1 = true;
	}
	public void OnExitEvent(BaseEventData eventData){
		OnActionEvent1 = false;
	}
}

You would add this to your EventSystem gameobject and use it to replace the automatically added StandaloneInputModule. You will need to setup some EventTriggers where pointer enter should call OnEnterEvent in this script and pointer exit should call OnExitEvent.

Hope that helps!

EDIT:

using UnityEngine;
using UnityEngine.EventSystems;
using System.Collections;

public class MyInputModule : StandaloneInputModule {
	public GameObject m_TargetObject;
	public bool WhileDown = false;
	public bool OnRelease = false;
	
	void Update(){
		if(Input.GetKeyDown(KeyCode.Q)){
			WhileDown = true;
		}
		if(Input.GetKeyUp(KeyCode.Q)){
			WhileDown = false;
			OnRelease = true;
		}
	}
	public override void Process(){
		if (m_TargetObject != null){
			if(WhileDown){
				ExecuteEvents.Execute(m_TargetObject, new BaseEventData(eventSystem), ExecuteEvents.selectHandler);
			}else if(OnRelease){
				ExecuteEvents.Execute(m_TargetObject, new BaseEventData(eventSystem), ExecuteEvents.deselectHandler);
				OnRelease = false;
			}
		}
		base.Process();
	}
}

Try this different script, You don’t need to set up TriggerEvents for this one! You should definitely only have one EventSystem gameobject, one script on the EventSystem will control the events for all the objects in your canvas. To change which object you want to select on Q press you need to just change the m_TargetObject to something, like a button gameObject.

I'll check this out later, but looks solid. Thanks for the detailed response!

So, I tried this solution, and while it works, I think it might be best to not use this method. I tried adding this script to a bunch of EventSystem gameobjects that are initially deactivated. When they are set to "Active", a very noticeable pause occurs. No idea why. I also receive a warning message from Unity stating that I shouldn't be using multiple EventSystems :p

Check my edit, you should only have one EventSystem object and only one instance of this script!

Ah, I get it now. I can see this will only work on one object at a time (at least in a single tick), but I can easily modify it to handle more. Thanks a lot!