Created
December 15, 2015 14:09
-
-
Save solarsailer/b88daecf0b77e29c70b0 to your computer and use it in GitHub Desktop.
Unity Screen Manager
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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