蛮牛地址:http://www.manew.com/thread-50564-1-1.html
官方地址:http://unitycodecontrol.com/tutorials/
一下内容根据自身理解,以及原文重新翻译了教程文档。并修复了其中我认为的一些错误。
Code Control MVC框架-创建一个Controller
介绍
这篇教程教会你怎样定义和实例化一个控制器。控制层就是控制模型层的类。它们常常负责更新一个基于对应模型层数据的可视化的组件,同时也负责根据用户的输入改变模型层的数据。
如果这是你第一次使用Code Control我们建议你先读一下上一篇。
The Model 模型层
控制层需要先有一个模型才能去控制它,所以咱们声明一个简单的模型先。
public class ExampleModel : Model {
//声明一个你自己的模型类,继承模型类
public Vector3 Position;
}
The Controller 控制层
现在我们已经声明好了模型,是时候声明控制器了。自定义的控制层应该继承
Controller类,这个T代表被控制的模型类型。
public class ExampleController : Controller<ExampleModel> {
//此处的案例将T换成了先前声明的类名<ExampleModel>
//用受保护的前缀重写父类正在初始化方法OnInitialize()
protected override void OnInitialize() {
// Initialize position based on Model
//根据模型初始化位置
transform.position = model.Position;
}
//用受保护的前缀重写父类正在改变模型方法OnModelChanged()
protected override void OnModelChanged() {
// Update position based on Model
//根据模型的位置来更新位置
transform.position = model.Position;
}
}
这个案例包含两个方法,都是从它们的基类Controller派生出来的。OnInitialize()方法是用来初始化基于模型数据的控制器。而OnModelChanged() 方法是用来在每一次模型数据被改变的时候更新控制器的。模型层的字段天生可以被控制层基类访问,这使得继承于该控制层基类的ExampleController可以获取/设置对应模型的数据。
控制层继承Unity的Monobehaviour类,因此也能访问任何其他的组件。通过更新它的transform的位置,ExampleController根据模型来更新它的视图(这里指它的空间位置显示)。
Instantiating the Controller 实例化控制器
接下来的代码展示的是如何实例化ExampleController。
public class ExampleGame : MonoBehaviour {
private void Awake() {
// Instantiate ExampleModel for the ExampleController
//为ExampleController实例化ExampleModel
ExampleModel model = new ExampleModel();
model.Position = new Vector3(1.0f, 0.0f, 1.0f);
// Instantiate the ExampleController as a component of an empty GameObject
//实例化ExampleController作为一个空对象的组件
Controller.Instantiate<ExampleController>(model);
}
}
为了实例化ExampleController, 我们需要提前实例化模型。毕竟,一个控制器总得需要控制点什么吧!
在改变一点点位置之后,我们通过Controller.Instantiate() 方法来实例化ExampleController,同时定义了该控制器的类型。这会实例化一个带有ExampleController组件的空游戏对象。调用ExampleController的初始化方法,使它根据我们指定的模型更新自己的位置。
为什么控制层把自己的数据放在一个单独的模型里呢?
拥有一个独立的模型类使得在将会被保存的数据和只会在运行时存在的字段之间有一个清楚的区别。通过保持模型和控制器的分离,使模型可以在实例化控制器之前被加载。这样让控制器完全依赖模型成为了可能,从而允许在游戏中实例化和从加载中实例化在同一条线程上。最后,通过分离模型和控制器,多个控制器可以使用同一个模型!
Changing the Model’s data 改变模型的数据
在ExampleController和 ExampleGame解耦的同时,我们仍然可以改变模型的数据。
public class ExampleGame : MonoBehaviour {
private void Awake() {
/* Previous code 之前的代码,忘记的童鞋可以回去再看看*/
// Change Model's data and notify it has been changed
//改变模型的数据并通知它已经被改变了
model.Position.y = 10.0f;
model.NotifyChange();
}
}
通过在模型上调用NotifyChange() 方法我们间接地调用了ExampleController的OnModelChanged()方法,同时让它更新它的视觉位置。这就是奇迹开始的地方;没有任何类需要一个让ExampleController工作的参数,因为它的所有输出是基于它的模型的。你可以使用Model Relations 监视器来获取一个可视化的哪部分代码在改变模型数据的视图。
为什么我必须在模型上手动地调用NotifyChange呢?
试想一下由于大量的类将需要改变模型里的数据,所以为什么NotifyChange方法没有被自动化调用也是一个合理的问题。最大的原因在于优化。想象一下我们需要在同一个模型上做五个改动,并且自动化会在每一次改动中在模型的控制器里面调用OnModelChanged方法。这样会多调用4次有木有!NotifyChange被写成手动,从而使它只在需要的时候才被调用。
Destroying the Controller 销毁控制器
控制器会在它的模型消失的同时自动销毁自己。我们来瞧瞧这是如何发生的。
public class ExampleGame : MonoBehaviour {
private void Awake() {
/* Previous code 之前的代码*/
// Delete the model, destroying the Controller
//删除模型,销毁控制器
model.Delete();
}
}
Conclusion 小结
通过在模型上调用Delete()方法我们将它从当前的环境中删除并自动地摧毁ExampleController所在的空游戏对象。使用Model Relations 监视器来获取一个可视化的哪部分代码在删除模型的视图。
在这部分教程中我们看到了如何声明一个模型和如何将它指派给一个控制器。控制层继承Monobehaviour类。它们基于其对应的模型被初始化并负责回应其对应模型的改变。我们学会了如何实例化一个控制器,和如何改变其对应模型的数据然后去影响到控制器的行为。最后,我们看到了如何通过删除模型来摧毁一个控制器。