链接地址:http://blog.csdn.net/huang9012/article/details/38491943
如果创建新的类时,使用的是在unity editor的project视图中右键,create javascript or c#方式,那么创建的类都是默认继承自MonoBehaviour, 生成后可以查看类文件,会发现c#类继承自MonoBehaviour, 虽然javascript的类前面没有这个继承自MonoBehaviour的关键字样,但是默认也是从它继承而来,这是unity的规定。
这样的类和普通没有继承自MonoBehaviour的类,有什么区别呢?区别很多,我们只说一点: 继承自MonoBehaviour的类,不需要自己创建它的实例,也不能自己创建(如 new 类名),编译的时候可以编译过去,但是执行的时候会给你一个错误在unity editor的console窗口,并且你new 后得到的东西为空;其实这是unity的一个bug,既然继承自MonoBehaviour的类不能new出来,为什么在编译的时候就给个错误,而是在运行时,如果没有看到unity editor的console窗口的内容真的很难知道为什么new的东西为空。
为什么不需要自己创建呢?因为所有从MonoBehaviour继承过来的类,unity都会自动创建实例,并且调用被重载的方法,如我们经常用到的Awake, Start, Update等。
而普通类,就可以用new来创建实例了。
在Unity脚本中使用继承和普通的C#没有多大区别,只要在父类只继承了MonoBehaviour就可以了,如果你将子类脚本贴到GameObject上,子类中如果有Awake,Start,Update等方法,将会覆盖父类中的这些方法,如果要掉用父类中的这些方法,可以使用base.Satrt(),base.Update().
使用泛型最大的好处就是代码复用,比如写一段程序要统计"水"的一些属性(信息),如这是什么样的水(矿泉水/自来水/污水.etc),或者水的温度是多少.可以这样写(使用结构体):
- public class NewBehaviourScript : MonoBehaviour
- {
- // Use this for initialization
- void Start()
- {
- Water test = new Water();
- test.name = "KuangQuanShui";
- test.temperature = 100;
- Debug.Log("水的名字: " + test.name + " 水的温度: " + test.temperature);
- }
- }
- public struct Water
- {
- public string name;//水的名字
- public int temperature;//水的温度
- }
下面是使用泛型来重写上面的这段代码,如下:
- public class fanxing : MonoBehaviour
- {
- // Use this for initialization
- void Start()
- {
- Water<string> test1 = new Water<string>();
- test1.info = "KuangQuanShui";//在此传入水的名字是"矿泉水"(可以将"T"看作是string类型)
- Water<int> test2 = new Water<int>();
- test2.info = 100;//在此传入水的温度是 100(可以将"T"看作是int类型)
- Debug.Log("水的名字: " + test1.info + " 水的温度: " + test2.info);
- }
- }
- public class Water<T>
- {
- public T info;//水的信息(属性)
- }
上面的"T"可以看作是任意数据类型,(对于为何不使用基类型object及涉及的装箱/拆箱,网上介绍的很详细了,在这就不过多叙述了)通过上面的两段代码可能还看不出泛型有多大的好处,但是想想如果是使用泛型来初始化单例,是不是方便很多.
对于泛型的约束:如果我只允许"T"接收某一个数据类型(比如自定义了一个构造函数,只接收这个类型)如下:
- public class fanxing : MonoBehaviour
- {
- // Use this for initialization
- void Start()
- {
- WaterBase waterInfo = new WaterBase();
- Water<WaterBase> test3 = new Water<WaterBase>();//Water<限定只能为WaterBase类型> 可以将"T"看作是WaterBase类型
- test3.info = waterInfo;
- test3.info.name = "KuangQuanShui";
- test3.info.temperature = 100;
- Debug.Log("水的名字是: " + test3.info.name + " 水的温度是: " + test3.info.temperature);
- }
- }
- public class Water<T> where T : WaterBase
- {
- public T info;//水的信息(属性) 可看作"T"的类型是WaterBase
- }
- public class WaterBase
- {
- public string name;
- public int temperature;
- }
泛型的约束,官网规定如下:
如果是多个占位符的泛型(两个),示例代码如下:
- public class fanxing : MonoBehaviour
- {
- // Use this for initialization
- void Start()
- {
- //从A产线出来的生产日期是string类型的"20130610",水是矿泉水,温度是20,
- Water<string, WaterBase> test1 = new Water<string, WaterBase>();//Water<任意类型,直接收WaterBase类型> 在此"T"相当于string类型
- test1.data = "20130610";
- test1.info.name = "KuangQuanShui";
- test1.info.temperature = 20;
- //从B产线出来的生产日期是int类型的20130610,水是纯净水,温度是20,
- Water<int, WaterBase> test2 = new Water<int, WaterBase>();//Water<任意类型,直接收WaterBase类型> 在此"T"相当于int类型
- test2.data = 20130610;
- test2.info.name = "ChunJingShui";
- test2.info.temperature = 20;
- }
- }
- public class Water<T, U> where U : WaterBase //限定"U"只能接收WaterBase类型
- {
- public T data;//出厂日期(可接受int型的20130610,或者string类型的"20130610");
- public U info;//水的具体信息(矿泉水/纯净水...温度)
- }
- public class WaterBase
- {
- public string name;
- public int temperature;
- }
接下来是泛型的继承,下面分别是一个占位符/多个占位符的继承示例,以及泛型继承的写法:
-
- public class fanxing : MonoBehaviour
- {
- // Use this for initialization
- void Start()
- {
- TestChild1 test = new TestChild1();