战场UI引发的一宗结构畅想

最近在编写公司项目的战场时,刻意使用Notification将战场逻辑与战场表现还有战场UI拆分为相互独立的三大模块。今天所想记录的就是在开发UI当中设计的一种结构,或许可以值得深入探索总结。

UI是什么?展现战场数据及信息,收集用户操作并向逻辑层、展现层发送通知,还有就是展示UI动画。不得不说我们的UI承担的东西还是挺多的,尤其UI动画,某种意义上它也是展现层的一部分,不过因为是在UI层展示,所以还是划入了UI层,却也发现了一些异常的好处。下面大概说说思路吧。

UI层只有一个总页面,放入我们的结构中来说,他只是一个BattlePage。它的子节点可以有多个MonoBehaviour,但是内部并没有Mono自身的Start、Update等函数,所以全部控制权都放在了BattlePage中。所有的子节点都定义为SubPage的派生类。

public class SubPage : MonoBehaviour
{
    
    public virtual void FirstOpen() { }
    
    public virtual void Tick(float delta) { }
    
    public virtual void FinalClose() { }

}

BattlePage自身包含页面的Open、Close、Update等方法,所以核心需要做的就是这么几点事了:

Open函数是页面第一次打开时候调用,所以在这里就需要通过GetComponentsInChildren获取子节点中所有的SubPage,并进行存储。之后调用所有SubPage的FirstOpen函数。

Close函数是页面最终关闭时候调用,所以在这里就需要对记录的所有SubPage执行它们的FinalClose函数。

Update函数则只需要简单执行SubPage的Tick方法即可,同时传入deltaTime参数。

public class BattlePage : Page
{
    List<SubPage> allSubPages;
    public override void PageOpen ()
    {
        allSubPages = new List<SubPage> (GetComponentsInChildren<SubPage> ());
        for (int i = 0, imax = allSubPages.Count; i < imax; i++) {
            allSubPages[i].FirstOpen ();
        }
    }
    public override void PageClose ()
    {
        for (int i = 0, imax = allSubPages.Count; i < imax; i++) {
            allSubPages[i].FinalClose ();
        }
    }
    private void Update ()
    {
        float deltaTime = Time.deltaTime;
        for (int i = 0, imax = allSubPages.Count; i < imax; i++) {
            allSubPages[i].Tick (deltaTime);
        }
    }
}

如此设计,BattlePage只是一个页面的管理器,内部则不需要再关注具体细节。而且一旦需要添加新的模块,只需要继承SubPage并添加到BattlePage成为其子节点,便可只关注内部具体实现。

那么SubPage的子类们究竟需要实现一些什么呢?由于采用MVC结构,并且整体是使用Notification实现,所以SubPage只需要实现这么几件事就可以:1.在FirstOpen中注册观察者及观察消息和对应的处理函数;2.在FinalClose中移除观察者;3.实现当前SubPage的具体UI展现逻辑。以我们项目中某英雄角色放大招之前的动画为例:页面在进入战场时注册大招观察者,收到消息即开始展示该英雄的大头贴动画,动画由SubPage自身的Tick实现,展示结束则广播展示结束通知消息,当战场关闭时便释放观察者。

public class HeroUIAnimPage : SubPage
{
    public override void FinalClose()
    {
        NotificationCenter.Default.RemoveObserver(this);
    }

    public override void FirstOpen()
    {
        NotificationCenter.Default.AddObserver(this, BeginPlay, "PlayHeroAnim", null);
    }

    private void BeginPlay(Notification notification)
    {
        // Begin Play UI Anim
    }

    public override void Tick(float delta)
    {
        // Play UI Anim
    }
}

经过现有开发阶段的验证,针对当前需求,采用此种开发模式效率高,且页面逻辑之间不存在耦合,修改也很快。

所以如果有人看到,希望大家一起交流

posted @ 2017-06-25 18:06  卅川  阅读(226)  评论(0)    收藏  举报