在uFrame 1.6的 Example Project裏有一個UserManagementSystem的系統(WinCondition這個eEnum是我之後加的,下文會再討論)
public class UserManagementService : UserManagementServiceBase
{
[Inject("LocalUser")] public UserViewModel LocalUser;
public override void Setup()
{
base.Setup();
// for develop only
LocalUser.AuthorizationState = AuthorizationState.Authorized;
//LocalUser.AuthorizationState = AuthorizationState.Unauthorized;
}
public void AuthorizeLocalUser(string Username, string Password)
{
if (Username == "uframe" && Password == "uframe")
{
Debug.Log("authorized in service");
LocalUser.AuthorizationState = AuthorizationState.Authorized;
}
}
}
這是處理Example Project內一開始登入的部份,就是確認登入成功後把AuthorizationState這個Enum轉成Authorized,方便在其他腳本檢查玩家的狀態。
我在想,是不是可以用UserManagementSystem內UserViewModel(我把這個instance命名為LocalUser, 上圖左上角)儲存玩家各種設定和資料,然後在不同場景不同的View 或 Controller的腳本把LocalUser取出來用或修改設定呢?
簡單說個例子,其中一個想做的功能就是在主畫面(有一個SetBattleScreenView)按不同作戰/勝利模式的按鈕,會修改LocalUser中WinCondition的設定,在進入作戰畫面後(另一個場景scene),而作戰畫面會檢查玩家在用哪個勝利模式(就是WinCondition),而運行不同的代碼。
(如果大家不了解uFrame MVVM模式可以來這裏了解一下:http://isaacforfun.blogspot.hk/2015/06/uframeflappy-brid.html)
但在uFrame的框架下,像UserManagementService腳本內用[Inject("LocalUser")]這個功能抓取LocalUser這個MVVM,只能在繼承了uFrame Service/ServiceBase才可以用!要是我在其他的View或Controller 的腳本是沒辦法用Inject抓取LocalUser的!
我苦惱了 OTL
後來我發覺了uFrame MVVM在版本1.6,新增Kernel的偉大!先簡單理解,Kernel就是一個在不同場景都會存在的東西,你能在Kernel內建立不同的Service,但這次先不討論這個。
(關於uFrame內的Kernel,可以來這裏認識一下:http://isaacforfun.blogspot.hk/2015/07/unity3duframe-16.html)
這次主要想說,其實Kernel一直都在儲存LocalUser這個UserViewModel!透過Kernel,我們可以用以下代碼在View, ViewModel, Controller 或uFrameComponent 的腳本把LocalUser抓下來用
public UserViewModel LocalUser;
LocalUser = uFrameKernel.Container.Resolve("LocalUser");
在SetBattleScreenView這個腳本﹐在InitializeViewModel先把LocalUser抓下來(記得在SetBattleScreenView的inspector激活Initialise ViewModel),然後按下Mission1Button這個按鈕,修改LocalUser的WinCondition,並轉換場景
protected override void InitializeViewModel(uFrame.MVVM.ViewModel model)
{
base.InitializeViewModel(model);
// NOTE: this method is only invoked if the 'Initialize ViewModel' is checked in the inspector.
// var vm = model as SetBattleScreenViewModel;
// This method is invoked when applying the data from the inspector to the viewmodel. Add any view-specific customizations here.
LocalUser = uFrameKernel.Container.Resolve("LocalUser");
Debug.Log (LocalUser == null ? "LocalUser is null" : LocalUser.Identifier);
}
public override void Bind()
{
base.Bind();
// Use this.SetBattleScreen to access the viewmodel.
// Use this method to subscribe to the view-model.
// Any designer bindings are created in the base implementation.
this.BindButtonToHandler (Mission1Button, () => {
if (LocalUser != null)
LocalUser.WinCondition = WinCondition.Tower;
//Move from MainMmenuScreen to MainGameScene
ChangetoMainGame();
});
}
轉換到作戰畫面後,因為我是用繼承uFrameComponent的腳本處理作戰場景的邏輯,所以要在KernelLoaded內抓取LocalUser。因為KernelLoaded 之後才會Initialize ViewModel,所以在View或Controller內直接在Initialize ViewModel裏抓Kernel內的東西就好了
public MainGameRootViewModel MainGameVM;
public UserViewModel LocalUser;
// Call when Kernel have been loaded
public override void KernelLoaded()
{
base.KernelLoaded();
LocalUser = uFrameKernel.Container.Resolve<UserViewModel>("LocalUser");
//對呀,我也可以這樣抓取作作戰系統(MainGameSystem)的ViewModel
MainGameVM = uFrameKernel.Container.Resolve<MainGameRootViewModel>("MainGameRoot");
MainGameVM.WinCondition = LocalUser.WinCondition;
}
得放多一次流程圖,事就這樣成了!
題外話:
近幾個月uFrame的支援變得不足,後來uFrame製作人親身在Slack(uFrame的群組)跟我們說自己的身體狀況欠佳,可以更新和支援比較慢,並說到最壞打算是Open Source uFrame的所有內容
今日製作人再跟我們說將會Open Source uFrame的所有內容,並在準備一份正式的通知和解釋背後的原因,這是一個沉重的決定......
然後剛剛有人發現uFrame MVVM和ECS已經是免費了
uFrame MVVM
uFrame ECS
待官方資料出來後,我再寫一篇個人感想吧,希望製作人身體健康吧~
為何不嘗試下Entitas
回覆刪除