- Home /
Switch between canvas
How would I go about switching between multiple canvas? Up until now I have just enabled and disabled the "canvas" component, but this means I can still interact with the buttons. I ran into this problem when I closed a canvas after opening it, and then jumped. This disabled the players movement scripts (like it should do when I open a canvas) and tried to do what the buttons were supposed to do. - So my question is, how would I go about switching between multiple canvas, without having to define every single canvas?
Answer by gorsefan · Jul 17, 2016 at 02:24 PM
I have a bunch of canvases I toggle on and off.
Short answer, the main thing is to get the UnityEngine.CanvasGroup's and set the .alpha .interactable and .blocksRaycasts properties, as desired.
Long answer; Here's an Abstract class the individual controller scripts for each canvas implement, it may be of use. It also fades them in & out. Client code must implement PostMenuClose() which can be custom code called when the manu/panel is closed. Take from it what you like :)
using UnityEngine;
using System.Collections;
public abstract class AbstractFadePanel : MonoBehaviour
{
protected UnityEngine.UI.Text[] textEls;
protected CanvasGroup RootCanvasGroup;
public abstract bool MenuOpen { get; protected set; }
public abstract void PostMenuClose ();
UnityEngine.UI.Image[] imageEls;
bool firstTime = true;
const float FADE_TIME = 0.2f;
void Awake ()
{
RootCanvasGroup = gameObject.GetComponentsInChildren<UnityEngine.CanvasGroup> () [0];
if (RootCanvasGroup == null)
RootCanvasGroup = gameObject.GetComponent<UnityEngine.CanvasGroup> ();
textEls = gameObject.GetComponentsInChildren<UnityEngine.UI.Text> (includeInactive: true);
imageEls = gameObject.GetComponentsInChildren<UnityEngine.UI.Image> (includeInactive: true);
}
/// <summary>
/// Toggles the visibility of the entire panel
/// </summary>
/// <param name="turnOn">If set to <c>true</c> turn on.</param>
public void ToggleVisibility (bool turnOn)
{
// Until used, the menus may exist in the editor in a crippled state
if (firstTime) {
RootCanvasGroup.alpha = 1;
RootCanvasGroup.interactable = true;
}
RootCanvasGroup.interactable = turnOn;
// Remove focus from the menu so arrow keys don't also move through widgets
// after it's been hidden.
UnityEngine.EventSystems.EventSystem.current.SetSelectedGameObject (null);
// Fade out constituent els
float targetAlpha = turnOn ? 1f : 0f;
foreach (var t in textEls)
t.CrossFadeAlpha (targetAlpha, FADE_TIME, false);
foreach (var i in imageEls)
i.CrossFadeAlpha (targetAlpha, FADE_TIME, false);
if (turnOn)
StartCoroutine (ForceInteractableRedraw ());
}
/// <summary>
/// Closes the menu
/// </summary>
protected void closeMenu ()
{
if (!UI.UIRegistry.GetClickLock ())
return;
RootCanvasGroup.interactable = false;
RootCanvasGroup.blocksRaycasts = false;
MenuOpen = false;
ToggleVisibility (turnOn: false);
PostMenuClose ();
}
/// <summary>
/// Opens the menu
/// </summary>
protected void openMenu ()
{
RootCanvasGroup.interactable = true;
RootCanvasGroup.blocksRaycasts = true;
MenuOpen = true;
ToggleVisibility (turnOn: true);
}
/// <summary>
/// For some reason toggling Interactable does not ensure the objects will
/// redraw correctly to reflect the new state. This forces it.
/// Note Canvas.ForceUpdateCanvases() sounds like it should address this, but couldn't
/// get it working in a quick test.
/// </summary>
/// <returns>The interactable redraw.</returns>
IEnumerator ForceInteractableRedraw ()
{
yield return new WaitForSeconds (0.04f);
RootCanvasGroup.interactable = false;
RootCanvasGroup.interactable = true;
}
}