淺談使用NGUI的界面架構(二)關於NData
PagePlayer.cs中:
public UILabel goldLabel;n public void SetGold( string gold )n {n goldLabel.text = gold;n }n
PagePlayer.cs中:
public UILabel goldLabel;n public UILabel goldLabel1;n public UILabel goldLabel2;n public void SetGold( string gold )n {n goldLabel.text = gold;n goldLabel1.text = gold;n goldLabel2.text = gold;n }n
2,不需要每次修改金幣的時候都要找到所有的金幣UILabel變數去修改他們的值。
初步的解決方案是這樣子的:我希望腳本裡面有一個值 gold代表的是金幣數量。所有的金幣UILabel 都跟這個值產生關聯。只要修改這個值,所有跟他關聯的UILabel 都自動發生變化。另外,在我要添加一個金幣UILabel 的時候,我希望它能自動去找頁面腳本中的gold變數來發生關聯,而不需要我在腳本中改代碼。具體實現的思路,就是在帶有UILabel腳本的物體上加一個腳本,使其與頁面腳本種的gold變數發生關聯。然後給gold變數加set方法,在這個方法中發一個消息,告知所有和gold有過關聯的的UILabel要發生值的改變。這樣每次給gold變數賦值的時候,所有與其關聯的UILabel就會自動更新顯示的內容。本著不重複造輪子的原則,在疑似開始造輪子之前一定要Google一下。於是在網上搜出了MVVM模式,NData插件等等。並發現NData不僅可以用於UILabel,還可以用於各種NGUI組件,並有很好的綁定層級管理。具體的用法這篇博客里已經寫的很清楚了NGUI 學習筆記實戰之二——商城數據綁定(Ndata)
NData就是基於MVVM模式,其中用戶自定義繼承EZData.Context的類,就相當於是自定義ViewModel層的內容。剩下的問題就是,怎樣用這個工具來管理頁面。根據上一篇文章 淺談使用NGUI的界面架構(一),我把界面分成很多個TweenPage,然後在單例MainPageMgr中統一管理。對於數據,我希望把每個頁面的數據也獨立出來,即每個頁面有一個對應的繼承EZData.Context的類,這個頁面相關的數據都放在這個類中,然後再由MainPageMgr來統一管理。
例如有個遊戲頁面PageInGame,用來顯示遊戲中獲得的金幣,鑽石和星星。現在新建一個PageInGameContext繼承EZData.Context。現在PageInGame頁面就有一個model層PageInGame類和一個ViewModel層PageInGameContext類。View層自然就是PageInGame物體下面的NGUI組件了。這樣就形成了MVVM模式。
using UnityEngine;nusing System.Collections;nnpublic class PageInGameContext : EZData.Contextn{n #region Property Goldnn private readonly EZData.Property<int> _privateGoldProperty = new EZData.Property<int> ();nn public EZData.Property<int> GoldProperty { get { return _privateGoldProperty; } }nn public int Gold {n get { return GoldProperty.GetValue (); }n set { GoldProperty.SetValue (value); }n }nn #endregionnnn #region Property Diamondnn private readonly EZData.Property<int> _privateDiamondProperty = new EZData.Property<int> ();nn public EZData.Property<int> DiamondProperty { get { return _privateDiamondProperty; } }nn public int Diamond {n get { return DiamondProperty.GetValue (); }n set { DiamondProperty.SetValue (value); }n }nn #endregionnn #region Property Starnn private readonly EZData.Property<int> _privateStarProperty = new EZData.Property<int> ();nn public EZData.Property<int> StarProperty { get { return _privateStarProperty; } }nn public int Star {n get { return StarProperty.GetValue (); }n set { StarProperty.SetValue (value); }n }nn #endregionnn}nnnnpublic class PageInGame : TweenPage {nn public PageInGameContext Context;nn nn protected override void Awake ()n {n base.Awake ();nn MainPageMgr.instance.Context.pageInGame = this;n Context = MainPageMgr.instance.Context.pageInGameCtx;nn }nn nnn protected override void OnPreBringIn ()n {n base.OnPreBringIn ();n nn }nn protected override void OnPreBringOut ()n {n base.OnPreBringOut ();n n }n}n
在MainPageMgr中有一個MainView Context是用來管理所有頁面的Context(下文中繼承EZData.Context的類,都統稱為Context。):
public class MainPageMgr : PageMgrSingleton<MainPageMgr>n{nn public NguiRootContext View;n //這個代表頁面模型n public MainView Context;nnnn void Awake()n {n n Context = new MainView();n SetContext();nnn }nn public void SetContext()n {n View.SetContext(Context);n }n}n
MainView.cs
public class MainView : EZData.Contextn{n n public MainView()n { n pageInGameCtx = new PageInGameContext();n }nn #region viewModel n public PageInGameContext pageInGameCtx{ get; private set; } n #endregionnn #region modeln public PageInGame pageInGame;n #endregionn}n
這樣,所有的頁面都可以通過MainPageMgr.instance.Context來獲取所有頁面的Context,如pageXXXContext,也可以獲得所有頁面的邏輯腳本,如pagXXX。
在場景里,只需要把頁面放在MainPageMgr的下級,然後再通過Master path來綁定到MainPageMgr中的Context就可以了。
在開發中,可能出現不同的頁面共用相同的數據,這種情況就可以直接把兩個頁面的Master Path綁定到同一個Context上,這樣開發起來會方便很多。總結:
引入NData這個插件,主要是為了減少一些對NGUI組件的操作(如獲取組件和賦值等),把所有的工作都簡化為改變Context中的值,來動態改變NGUI組件的顯示。把各個頁面的Context都統一管理,是為了更方便地獲取數據,但原則上不應該在A頁面的model層中去修改B頁面Context中的數據,因為這樣容易造成混亂。
使用NData加NGUI,可以很快速地搭建一套頁面框架。現在我已經把這兩個工具專門打成插件包,開發新項目時直接導進去用,非常方便。
推薦閱讀:
※Unity3D熱更新LuaFramework入門實戰(7)——PureMVC
※Unity自動化構建之iOS打包(另有Android篇)
※微表面模型-PBR渲染管線的材質
※Unity線性空間下移動設備上烘焙變暗問題處理
※UWA GOT v1.1 | 支持本地管理深度測評、全新的UWA API、兼容Unity 2017.3