Skip to content

Instantly share code, notes, and snippets.

@solarsailer
Created December 15, 2015 14:09
Show Gist options
  • Save solarsailer/b88daecf0b77e29c70b0 to your computer and use it in GitHub Desktop.
Save solarsailer/b88daecf0b77e29c70b0 to your computer and use it in GitHub Desktop.
Unity Screen Manager
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections;
// Based on http://docs.unity3d.com/Manual/HOWTO-UIScreenTransition.html tutorial.
public class ScreenManager : MonoBehaviour
{
#region Constants
public const string PARAMETER_VISIBILITY = "IsVisible";
public const string SHOW_ANIMATION = "Show";
public const string HIDE_ANIMATION = "Hide";
#endregion
#region Members
// First screen to show.
public Animator initialScreenAnimator;
// Current screen's animator.
private Animator currentScreenAnimator;
// Reference to the transition parameter.
private int isVisibleParameter;
// The GameObject Selected before we opened the current Screen.
// Used when closing a Screen, so we can go back to the button that opened it.
private GameObject previousSelectedObject;
#endregion
#region Timeline
public void Awake()
{
instance = this;
}
public void OnEnable()
{
// Store a reference to the parameter we use to trigger the transitions.
isVisibleParameter = Animator.StringToHash(PARAMETER_VISIBILITY);
// Do nothing if no initial screen provided.
if (initialScreenAnimator == null)
{
return;
}
ShowScreen(initialScreenAnimator);
}
#endregion
#region Methods
// Show the provided screen and change the navigation/selection.
public void ShowScreen(Animator screenAnimator)
{
if (currentScreenAnimator == screenAnimator)
{
return;
}
// Store the current selected object so we can revert its state
// when we dismiss this screen later.
previousSelectedObject = EventSystem.current.currentSelectedGameObject;
// Activate and move to front.
screenAnimator.gameObject.SetActive(true);
screenAnimator.transform.SetAsLastSibling();
HideCurrentScreen();
// Start the Show transition.
currentScreenAnimator = screenAnimator;
currentScreenAnimator.SetBool(isVisibleParameter, true);
// Set an object of the new screen as the selection.
SetSelected(FindFirstEnabledSelectable(screenAnimator.gameObject));
}
// Hide the current screen and change the navigation/selection.
public void HideCurrentScreen()
{
if (currentScreenAnimator == null)
{
return;
}
// Start the Hide animation.
currentScreenAnimator.SetBool(isVisibleParameter, false);
// Revert the selection to the previously selected game object.
SetSelected(previousSelectedObject);
// Disable the game animator as soon as the animation is over.
StartCoroutine(DisableScreenAfterAnimation(currentScreenAnimator));
// No screen open.
currentScreenAnimator = null;
}
// Deactivate the game object as soon as the animation is over.
private IEnumerator DisableScreenAfterAnimation(Animator hideAnimation)
{
var hasReachedHiddenState = false;
var isOver = true;
while (!hasReachedHiddenState && isOver)
{
if (!hideAnimation.IsInTransition(0))
{
hasReachedHiddenState = hideAnimation.GetCurrentAnimatorStateInfo(0).IsName(HIDE_ANIMATION);
}
isOver = !hideAnimation.GetBool(isVisibleParameter);
yield return new WaitForEndOfFrame();
}
if (isOver)
{
hideAnimation.gameObject.SetActive(false);
}
}
private void SetSelected(GameObject go)
{
EventSystem.current.SetSelectedGameObject(go);
}
#endregion
#region Static
private static ScreenManager instance;
public static void Show(Animator a)
{
if (instance != null)
{
instance.ShowScreen(a);
}
}
public static void Hide()
{
if (instance != null)
{
instance.HideCurrentScreen();
}
}
// Find the first `Selectable` element in the provided hierarchy.
public static GameObject FindFirstEnabledSelectable(GameObject gameObject)
{
GameObject go = null;
var selectables = gameObject.GetComponentsInChildren<Selectable>(true);
foreach (var selectable in selectables)
{
if (selectable.IsActive() && selectable.IsInteractable())
{
go = selectable.gameObject;
break;
}
}
return go;
}
#endregion
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment