程序中的每个界面都有很多共性,比如每个界面都会有进入动画和退出动画(即使是硬切换没有任何动画,也至少有进入动作和退出动作,需要SetActive)。为了方便管理每个界面,把更多的精力放在将动画处理得更加平滑和精致上,一个界面管理工具是很必要的。这里提供一个解决方案,利用栈来存储每个界面,每个界面都有从上级或下级界面进入,退出到上级或下级界面四个协程来管理动画。
首先我们需要一个抽象的基类来管理每个界面,包括界面名字(供查找)和四个Unity事件来支持每个动画完成之后的回调。
RootUIPanel:
using UnityEngine;
using System.Collections;
using UnityEngine.Events;
public abstract class RootUIPanel : MonoBehaviour
{
/// <summary>
/// 界面的名字(供查询与跳转使用)
/// </summary>
[Tooltip("界面的名字(供查询与跳转使用)")]
public string panelName;
/// <summary>
/// 从上一个界面进入时的事件
/// /// </summary>
[Tooltip("从上一个界面进入时的事件")]
public UnityEvent action4EnterFromPre;
/// <summary>
/// 从下一个界面返回时的事件
/// /// </summary>
[Tooltip("从下一个界面返回时的事件")]
public UnityEvent action4EnterFromNext;
/// <summary>
/// 返回之前的界面时的事件
/// /// </summary>
[Tooltip("返回之前的界面时的事件")]
public UnityEvent action4ExitToPre;
/// <summary>
/// 进入下一个界面时的事件
/// /// </summary>
[Tooltip("进入下一个界面时的事件")]
public UnityEvent action4ExitToNext;
/// <summary>
/// 从上一个界面进入
/// </summary>
/// <returns></returns>
public abstract IEnumerator OnPanelEnterFromPre();
/// <summary>
/// 从下一个界面返回
/// </summary>
/// <returns></returns>
public abstract IEnumerator OnPanelEnterFromNext();
/// <summary>
/// 返回之前的界面
/// </summary>
/// <returns></returns>
public abstract IEnumerator OnPanelExitToPre();
/// <summary>
/// 进入下一个界面
/// </summary>
/// <returns></returns>
public abstract IEnumerator OnPanelExitToNext();
}
当然为了确保安全,我们可以对每个界面的名字进行检查,有相同名字的界面出现时不允许的,需要报错或者对用户进行警告。
在界面管理工具中,我们将每个被激活的界面入栈,进入下一个界面是直接将下一个界面入栈并显示,返回上一界面时将当前界面出栈并显示之后的栈顶界面。每一个界面都存储在Dictionary中,通过界面名字来查找以供栈来使用。
进入一个界面时,我们调用一个GotoPanel方法,并使用协程来实现动画:
public void GotoPanel(string to)
{
StartCoroutine(_enterPanel(to));
}
private IEnumerator _enterPanel(string to)
{
var curPanel = panelStack.Peek() as RootUIPanel;
var nextPanel = panelDic[to];
panelStack.Push(nextPanel);
yield return StartCoroutine(curPanel.OnPanelExitToNext());
if (curPanel.action4ExitToNext != null)
curPanel.action4ExitToNext.Invoke();
curPanel.gameObject.SetActive(false);
nextPanel.gameObject.SetActive(true);
yield return StartCoroutine(nextPanel.OnPanelEnterFromPre());
if (nextPanel.action4EnterFromPre != null)
nextPanel.action4EnterFromPre.Invoke();
}
调用界面的返回功能时,调用一个BackFuntion方法,并使用协程管理动画:
public void BackFunction()
{
StartCoroutine(_backFuntion());
}
private IEnumerator _backFuntion()
{
var curPanel = panelStack.Pop() as RootUIPanel;
var nextPanel = panelStack.Peek() as RootUIPanel;
yield return StartCoroutine(curPanel.OnPanelExitToPre());
if (curPanel.action4ExitToPre != null)
curPanel.action4ExitToPre.Invoke();
curPanel.gameObject.SetActive(false);
nextPanel.gameObject.SetActive(true);
yield return StartCoroutine(nextPanel.OnPanelEnterFromNext());
if (nextPanel.action4EnterFromNext != null)
nextPanel.action4EnterFromNext.Invoke();
}
然后只需要给每个界面写一个界面脚本继承RootUIPanel,并实现四个出入动画,就能简单的管理界面了。因为使用了协程,在进行稍微复杂的逻辑处理的时候要注意共享数据操作处理的安全性。
这里只介绍方案思路,完成的界面管理代码就不放出了。
by:蒋志杰