strangeioc test learn
来源:互联网 发布:电视直播点播软件 编辑:程序博客网 时间:2024/06/09 23:52
strangeioc test learn
文中所有步骤根据StrangeIoc框架示意图来的,这个图得下载地址:http://pan.baidu.com/s/1hs3bOAo
我们首先要创建root,作为启动框架的脚本,资料里面说这个类还做了初始化,到底是什么初始化,暂时也还不了解,先创建出来再修改。
/// <summary>/// 图解上面的ROOT创建完成,用作启动框架/// </summary>public class Demo1ContextView : ContextView { void Awake() { this.context=new Demo1Context(this); }}
挂载在层次面板中的空物体身上:
按照图解第二步应该是创建MVCSContext,这个脚本做了为框架做了哪些职责?用来做模块绑定映射的,映射是StrangeIoc框架一个核心点
/// <summary>/// 框架中的MVCS Context创建完成,用来做 进行绑定映射/// </summary>public class Demo1Context : MVCSContext { public Demo1Context(MonoBehaviour view) : base(view) { } //进行绑定映射 protected override void mapBindings() { //绑定映射分为四类绑定 //model injectionBinder.Bind<ScoreModel>().To<ScoreModel>().ToSingleton();//数据模型绑定 //server injectionBinder.Bind<IScoreService>().To<ScoreService>().ToSingleton();//指定执行IScoreService绑定ScoreService //command commandBinder.Bind(Demo1CommandEvent.REQUEST_SCORE).To<RequestScoreCommand>(); commandBinder.Bind(Demo1CommandEvent.UPDATE_SCORE).To<UpdateScoreCommand>(); //mediator mediationBinder.Bind<CubeView>().To<CubeMediator>();//完成view和mediator的绑定 //既然我们已经创建了一个开始命令*(StartCommand),这个命名 //是要立即调用的,接下来做命令绑定 commandBinder.Bind(ContextEvent.START).To<StartCommand>().Once(); //once 表示只会触发一次 }}因为StartCommand是要首先立即调用的,前面的model,server,command,mediator绑定之后不是立即调用,model,server..都是后续完善的。
/// <summary>/// 这是我们的开始命名,需要继承控制器 做一些初始化操作/// </summary>public class StartCommand : Command{ /// <summary> /// 当这个命名被执行的时候,会默认调用Excute方法 /// </summary> public override void Execute() { Debug.LogError("Start StrangeIoc FrameWork..."); }}
点击运行游戏,测试效果图:
创建分数模型,和Iscoreservice接口
/// <summary>/// 数据模型 承载数据就行,并不需要继承/// </summary>public class ScoreModel{ public int Score { get; set; }}
/// <summary>/// 创建service接口/// </summary>public interface IScoreService { //模拟连接服务器请求分数 void RequestScore(string url); //模拟收到分数 void OnReceiveScore(); //模拟更新分数 void UpdateScore(string url, int score); IEventDispatcher dispatcher { get; set; }}
接下来在service中创建Scoreservice用来实现接口
public class ScoreService : IScoreService { public void RequestScore(string url) { Debug.LogError("Request score from url:" + url); OnReceiveScore(); } public void OnReceiveScore() { //模拟服务器接收到的数据 int score = Random.Range(1, 100); //开始派送事件(通知事件) dispatcher.Dispatch(Demo1ServiceEvent.REQUEST_SCORE,score); } public void UpdateScore(string url, int score) { Debug.LogError("Update score to url" + url + "new score" + score);//给服务器更新分数 } /* 注入 */ [Inject] public IEventDispatcher dispatcher { get; set; }}
第二部分 视图层 view 和mediator
public class CubeView : View{ private float mCountTimer = 0f; public Text mText; [Inject] public IEventDispatcher dispatcher { get; set; } //局部的派送器 /// <summary> /// 初始化函数(由对应的mediator来调用,如CubeMediator) /// </summary> public void Init() { } /// <summary> /// 游戏体自身控制逻辑 /// </summary> void Update() { mCountTimer += Time.deltaTime; if (mCountTimer > 0.5f) { this.transform.position = (new Vector3(Random.Range(-11, 10), Random.Range(-2, 5), 0)); mCountTimer = 0f; } } /// <summary> /// 玩家交互 /// </summary> void OnMouseDown() { print("click this gameobject."); //in... //玩家点击之后开始要涨分数,所以从这里开始调用框架 // 其实内部逻辑是一个事件管理器的注册与通知,同时事件id为枚举类型 dispatcher.Dispatch(Demo1MediatorEvent.CLICKDOWN); } /// <summary> /// 提供给外界用来更新UI分数的方法(由对应的mediator来调用,如CubeMediator) /// </summary> /// <param name="score"></param> public void UpdateScore(int score) { mText.text = score.ToString(); }}
view层和外界的交互是通过mediator,一个view对应一个mediator
/// <summary>/// 每个模块(view)对应一个自身的mediator/// </summary>public class CubeMediator : Mediator{ /* 注入:是为了方便访问数据,比如注入view,model..... */ [Inject] //依赖注入 //将对应的view注入进来,这个脚本会自动添加到view模块上面 //见下面图示 public CubeView cubeView { get; set; } [Inject] public ScoreModel scoreModel { get; set; } [Inject(ContextKeys.CONTEXT_DISPATCHER)]//全局dispatch //一定要添加任何地方都可以这么访问到全局派发器 public IEventDispatcher dispatcher { get; set; } /// <summary> /// 注册,模块激活时调用,当挂载到对应模块上面时候 /// </summary> public override void OnRegister() { cubeView.Init(); dispatcher.AddListener(Demo1MediatorEvent.SCORECHANGE, OnScoreChange); cubeView.dispatcher.AddListener(Demo1MediatorEvent.CLICKDOWN, OnClickDown); //通过dispatcher发起请求分数的命令 dispatcher.Dispatch(Demo1CommandEvent.REQUEST_SCORE); } /// <summary> /// 解注册 模块销毁时候调用,解注册所有之前添加的事件 /// </summary> public override void OnRemove() { dispatcher.RemoveListener(Demo1MediatorEvent.SCORECHANGE, OnScoreChange); cubeView.dispatcher.RemoveListener(Demo1MediatorEvent.CLICKDOWN, OnClickDown); } /// <summary> /// CubeMediator向CubeView回传数据的CallBack /// </summary> /// <param name="varEvt">回传的服务器数据</param> public void OnScoreChange(IEvent varEvt) { //int varData = (int) varEvt.data;//解包数据 //scoreModel.Score = (int) varEvt.data; 这里也可与注入数据模型 //取数据模型当中数据 cubeView.UpdateScore(scoreModel.Score); // cubeView.UpdateScore(varData); } /// <summary> /// 加分函数 /// </summary> public void OnClickDown() { dispatcher.Dispatch(Demo1CommandEvent.UPDATE_SCORE); }}
第三部分 创建Command命令,模块之间的通信通过dispatch来进行...在mediator里面访问dispatch,这样就降低了模块的耦合性。在此之前我们先定义好事件id类型
/// <summary>/// 命令类型/// </summary>public enum Demo1CommandEvent{ REQUEST_SCORE, UPDATE_SCORE,}
/// <summary>/// 分数模块的事件类型/// </summary>public enum Demo1MediatorEvent{ SCORECHANGE,//1 CLICKDOWN,}
/// <summary>/// 服务器事件类型/// </summary>public enum Demo1ServiceEvent{ REQUEST_SCORE,}
看看是如何进行绑定的,没有绑定模块之间的通信就构建不起来。
/// <summary>/// Command要和事件id绑定起来,在context里面进行绑定/// </summary>public class RequestScoreCommand : EventCommand { //please check context binding...... /* //绑定映射分为四类绑定 //model injectionBinder.Bind<ScoreModel>().To<ScoreModel>().ToSingleton();//数据模型绑定 //server injectionBinder.Bind<IScoreService>().To<ScoreService>().ToSingleton();//指定执行IScoreService绑定ScoreService //command commandBinder.Bind(Demo1CommandEvent.REQUEST_SCORE).To<RequestScoreCommand>(); commandBinder.Bind(Demo1CommandEvent.UPDATE_SCORE).To<UpdateScoreCommand>(); //mediator mediationBinder.Bind<CubeView>().To<CubeMediator>();//完成view和mediator的绑定 */ [Inject] public IScoreService scoreService { get; set; } /// <summary> /// 注入数据模型 /// </summary> [Inject] public ScoreModel scoreModel { get; set; } /* 访问全局派发器的方式 /// <summary> /// 访问全局派发器 /// </summary> [Inject(ContextKeys.CONTEXT_DISPATCHER)] public IEventDispatcher dispatcher { get; set; } 或者将command继承修改成eventCommand */ public override void Execute() { /* tip:prevent destory. */ Retain(); //注册派送器:派送标签 Demo1ServiceEvent.REQUEST_SCORE 派送事件:OnComplete /* notice:waring register dispatcher handler pos. */ scoreService.dispatcher.AddListener(Demo1ServiceEvent.REQUEST_SCORE, OnComplete); scoreService.RequestScore("http://www.ciso.com"); } /// <summary> /// 服务器回包 /// </summary> /// <param name="varEvt">回包数据</param> void OnComplete(IEvent varEvt) { Debug.LogError("Request score from server :" + varEvt.data); //销毁注册的派送器 scoreService.dispatcher.RemoveListener(Demo1ServiceEvent.REQUEST_SCORE,OnComplete); //将服务器回包数据存于数据模型中 scoreModel.Score = (int) varEvt.data; //将回包数据传递给 CubeMediator dispatcher.Dispatch(Demo1MediatorEvent.SCORECHANGE, varEvt.data); /* tip:release,used to save resources */ Release(); }}
只有通过了绑定才能在mediator里面通过事件注册通知的方式去发送请求。
//通过dispatcher发起请求分数的命令 dispatcher.Dispatch(Demo1CommandEvent.REQUEST_SCORE);
好接下来我们通过图解来更加深入的了解一下这个流程:
创建更新分数Command命令,并进行绑定。
public class UpdateScoreCommand : EventCommand{ [Inject] public ScoreModel scoreModel { get; set; } [Inject] public IScoreService scoreService { get; set; } public override void Execute() { int varData=scoreModel.Score++; scoreService.UpdateScore("http://www.ciso.com", varData); dispatcher.Dispatch(Demo1MediatorEvent.SCORECHANGE,varData); }}
所有的数据请求,数据回传都是通过全局的dispatch来实现的,这样能够将各个模块之间的耦合性降低,提高效率。最后还是使用图解和文字将“请求分数”“回传分数”“显示分数”进行解释,能够使自己对这个流程能够有更加深入细致的理解,了解游戏分层思想!
首先,模块入口是从下面这个玩家交互开始的:
接下里开始寻找哪里注册了这个事件类型,由于我们知道Cubeview视图层,每个视图层都有一个Mediator进行对应,主要用来处理模块之前的沟通通信,那我们来到这个脚本,可以看到对应的事件类型(Demo1MediatorEvent.CLICKDOWN),前请提示,之所以我们能这么做是因为我们在ContextView里面进行了view和各自mediator的绑定
好,我们接着看CubeMediator脚本
由于这里只是在模块激活时进行了提前注册,所以当玩家点击事件之后,全局派发器进行事件派发(通知),我们就会来到这里执行后面的对应的函数(/委托),那我们看看OnClickDown函数执行了什么?
我们回到ContextView可以看到,到底是谁和上面的事件id进行绑定
这里我们需要知道,当全局派发器进行派发的时候,根据事件id进行派发的,比如上面这个,很明显它是和UpdateScoreCommand这个脚本进行了绑定,所以全局派发器执行后,会自动跳转到这个脚本内部执行excute函数:
接着我们再看哪里注册对应这个事件id类型,很明显我们又在CubeMediator里面找到注册的地方
开始执行OnScoreChange函数:
好了,这里就完成服务器数据的回传。其实整体结构流程和MVC框架大致相同,不同的是StrangeIOC开创了binding方式和全局派发器的使用,关于请求分数的部分,自己可以多多练习,这里就不详细叙述了。
ps:
我也是第一次开始接触strangeioc框架学习,所以本文难免有疏漏之处,还望多多见谅。
- strangeioc test learn
- MapReduce Learn Test
- Distributed File System Learn Test
- how to learn unit test mock framework
- Unity MVC框架 StrangeIoC
- 项目架构strangeioc
- Unity StrangeIoC HelloWorld
- Unity StrangeIoC框架
- StrangeIoC框架学习
- StrangeIoc MVCS游戏框架
- Get Start StrangeIOC for Unity3D
- Get Start StrangeIOC for Unity3D
- unity框架strangeioc研究分享
- Get Start StrangeIOC for Unity3D
- Get Start StrangeIOC for Unity3D
- StrangeIoc框架的简要介绍
- StrangeIoc框架的详细介绍
- StrangeIOC翻译 the-big-strange
- kruskal算法
- <HTML> 给input文本框中添加灰色提示字
- 12 duplicate symbols for architecture armv7
- LeetCode 342. Power of Four
- Direct3D的四大变换
- strangeioc test learn
- 学习学习
- for 续4
- C语言逗号运算符和逗号表达式
- Ajax请求Json遇到的问题总结
- 模块继续
- Ubuntu mysql 安装
- poj2217 后缀数组
- 为什么你要写博客?(见过最赞的回答)