### ScreenManager Implementation Source: https://docs.unity3d.com/Packages/com.unity.ugui%401.0/manual/HOWTO-UIScreenTransition.html A MonoBehaviour script that manages opening and closing UI panels using Animator states and EventSystem navigation. ```csharp using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems; using System.Collections; using System.Collections.Generic; public class ScreenManager : MonoBehaviour { //Screen to open automatically at the start of the Scene public Animator initiallyOpen; //Currently Open Screen private Animator m_Open; //Hash of the parameter we use to control the transitions. private int m_OpenParameterId; //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 m_PreviouslySelected; //Animator State and Transition names we need to check against. const string k_OpenTransitionName = "Open"; const string k_ClosedStateName = "Closed"; public void OnEnable() { //We cache the Hash to the "Open" Parameter, so we can feed to Animator.SetBool. m_OpenParameterId = Animator.StringToHash (k_OpenTransitionName); //If set, open the initial Screen now. if (initiallyOpen == null) return; OpenPanel(initiallyOpen); } //Closes the currently open panel and opens the provided one. //It also takes care of handling the navigation, setting the new Selected element. public void OpenPanel (Animator anim) { if (m_Open == anim) return; //Activate the new Screen hierarchy so we can animate it. anim.gameObject.SetActive(true); //Save the currently selected button that was used to open this Screen. (CloseCurrent will modify it) var newPreviouslySelected = EventSystem.current.currentSelectedGameObject; //Move the Screen to front. anim.transform.SetAsLastSibling(); CloseCurrent(); m_PreviouslySelected = newPreviouslySelected; //Set the new Screen as then open one. m_Open = anim; //Start the open animation m_Open.SetBool(m_OpenParameterId, true); //Set an element in the new screen as the new Selected one. GameObject go = FindFirstEnabledSelectable(anim.gameObject); SetSelected(go); } //Finds the first Selectable element in the providade hierarchy. static GameObject FindFirstEnabledSelectable (GameObject gameObject) { GameObject go = null; var selectables = gameObject.GetComponentsInChildren (true); foreach (var selectable in selectables) { if (selectable.IsActive () && selectable.IsInteractable ()) { go = selectable.gameObject; break; } } return go; } //Closes the currently open Screen //It also takes care of navigation. //Reverting selection to the Selectable used before opening the current screen. public void CloseCurrent() { if (m_Open == null) return; //Start the close animation. m_Open.SetBool(m_OpenParameterId, false); //Reverting selection to the Selectable used before opening the current screen. SetSelected(m_PreviouslySelected); //Start Coroutine to disable the hierarchy when closing animation finishes. StartCoroutine(DisablePanelDeleyed(m_Open)); //No screen open. m_Open = null; } //Coroutine that will detect when the Closing animation is finished and it will deactivate the //hierarchy. IEnumerator DisablePanelDeleyed(Animator anim) { bool closedStateReached = false; bool wantToClose = true; while (!closedStateReached && wantToClose) { if (!anim.IsInTransition(0)) closedStateReached = anim.GetCurrentAnimatorStateInfo(0).IsName(k_ClosedStateName); wantToClose = !anim.GetBool(m_OpenParameterId); yield return new WaitForEndOfFrame(); } if (wantToClose) anim.gameObject.SetActive(false); } //Make the provided GameObject selected //When using the mouse/touch we actually want to set it as the previously selected and //set nothing as selected for now. private void SetSelected(GameObject go) { //Select the GameObject. EventSystem.current.SetSelectedGameObject(go); //If we are using the keyboard right now, that's all we need to do. var standaloneInputModule = EventSystem.current.currentInputModule as StandaloneInputModule; if (standaloneInputModule != null) return; //Since we are using a pointer device, we don't want anything selected. //But if the user switches to the keyboard, we want to start the navigation from the provided game object. //So here we set the current Selected to null, so the provided gameObject becomes the Last Selected in the EventSystem. EventSystem.current.SetSelectedGameObject(null); } } ``` -------------------------------- ### Enabling Rich Text in Editor GUI Source: https://docs.unity3d.com/Packages/com.unity.ugui%401.0/manual/StyledText.html Configure a GUIStyle with richText enabled to render styled text within Editor GUI elements. ```csharp GUIStyle style = new GUIStyle (); style.richText = true; GUILayout.Label("Some RICH text",style); ``` -------------------------------- ### Implement the custom message interface Source: https://docs.unity3d.com/Packages/com.unity.ugui%401.0/manual/MessagingSystem.html Implement the custom interface in a MonoBehaviour to define the logic executed when a message is received. ```csharp public class CustomMessageTarget : MonoBehaviour, ICustomMessageTarget { public void Message1() { Debug.Log ("Message 1 received"); } public void Message2() { Debug.Log ("Message 2 received"); } } ``` -------------------------------- ### Define a custom message interface Source: https://docs.unity3d.com/Packages/com.unity.ugui%401.0/manual/MessagingSystem.html Create an interface inheriting from IEventSystemHandler to define methods that can be invoked by the messaging system. ```csharp public interface ICustomMessageTarget : IEventSystemHandler { // functions that can be called via the messaging system void Message1(); void Message2(); } ```