书本阅读时的一些概要笔记。
C#运行时和虚拟机非常相似,可能和原生宿主的C/C++进行交互。C#有不同的版本,不同的Unity支持的版本不一样。另外,Mono和.Net框架自带的类库不同。 Unity 2017.1可使用.NET4.6和C#6。 也可以使用.net3.5和C#3。而C#3/6版本 分别对应的就是VS2008/2015版本。
- Centos安装C#环境
了解IL2CPP和Mono区别。IL2CPP是Mono的替代品。
- 在不指定基类时,默认继承自System.Object, 于是有了几个基础方法。
- C#3版本中,var关键字实现的是编译期就可以确定的类型。而C#4的dynamic定义的变量,是真正的动态类型。类型LPC的mixed类型。但在Unity中只能使用C#3
- 引用和值类型对象主要差别是,一个来自托管堆分配,后者一般来自栈分配。前者涉及GC机制和昂贵的内存申请和初始化操作,后者不需要。比如class是引用类型,而struct是值类型。 值类型不可当作基类,他没有额外的类型信息。于是有了引用和值类型的区别。
- 在堆上分配的值类型:数组中的元素、引用类型中的值类型字段、迭代器块中的局部变量、闭包情况下匿名函数(lamda)中的局部变量。因为变量这些需要在栈销毁后还要用到。
引用类型举例:
- 自定义引用类型:Class、Interface 、Delegate。
- 内建的引用类型有:Dynamic、Object(System.Object) 、string (System.String, 只读)
- 类库中的其他引用类型: System.Collections.Generic.List类、System.Text.Decoder等。
值类型
结构类值类型(派生自System.ValueType)
- 数字型结构: 常见的System.Int32 , System.Float, System.Decimal等
- 布尔结构:System.Boolean
- 自定义结构(使用struct关键字定义的)。使用new关键字创建,但不是从堆分配!
- 内置的DateTime类型其实也是结构类型, 他有自己的方法。
- 枚举类型。(派生自System.Enum, 而System.Enum又派生自System.ValueType)
如Sytem.IO.FileAttributes、System.Drawing.FontStyle等.
值类型的特征:
- 不能派生出其他类型。因此不能加新的虚方法或者抽象方法。
- 不需要从其他类型中派生。
- 值不可变。值类型没有提供更改其值的成员,称为不可变。
- 值传递。在传参、返回中复制。因为最好不要太大。
- 有未装箱和已装箱两种表示方式。装箱指把值类型转化为引用类型。比如转化为obect类型。
- 值类型派生自System.ValueType,而System.ValueType派生自System.Object. System.ValueType重写了GetHashCode\Equals两个方法。
值类型的装箱和拆箱:
- 装箱. 就是将不在托管堆且不受GC机制影响的的值类型变量,转化为引用类型。本质是在托管堆中分配内存(所以托管堆对象都有额外的类型对象指针和同步索引块)。然后复制值得到堆中。最后返回引用。
- 拆箱.就是获得已装箱对象中各地址。不包含复制。当拆箱一个struct后,如果使用到这个结构中字段时,才进行复制这个字段。
Unity的引用类型
UnityEngine.Object
类:所有Unity中的对象都继承自UnityEngine.Object
类。所有派生自这个类的公开变量都会被显示在监视器(inspector)窗口中。开发者可以很方便的通过编辑器修改这些值。这个类也提供了静态的创建、查找、销毁方法。UnityEngine.Component
类:他是UnityEngine.Object
类的子类。同时他也是所有可以添加到游戏对象GameObject
上的组件(Component)的基类。基本上他和游戏对象有明确的绑定关系,他提供了获取游戏对象标签、Transform
组件、调用游戏对象及其子对象的方法、获得游戏对象及其子对象上其他的组件。常用方法是GetComponect<T>
、GetComponects<T>
、BroadcastMessage
方法等。获取组件一般第一次调用后缓存目标对象的引用,来提交效率。UnityEngine.Behaviour
类:继承自UnityEngine.Component
. 这个中间类可以控制开启和禁用引擎的每帧Update
回调。UnityEngine.MonoBehaviour
类:他继承自UnityEngine.Behaviour
。所有的脚本都派生自MonoBehaviour
类。每完成一个C#脚本时都要显式继承这个类。而且不能使用new
来创建MonoBehaviour
类及其子类的对象实例。可以使用gameObject.AddComponent<T>()
接口来动态把脚本挂载到指定的游戏对象,从而间接创建实例。这个类提供了协程控制、引擎帧更新等回调、GUI事件回调。引擎回调顺序如下:- 当前场景中所有游戏对象的Reset、Awake、OnEnable方法,会在所有的Start、Update等方法之前调用。
- 第一帧更新前,调用Start, 他在所有对象的Update前调用。Awake(prefab实例化后)、OnEnable、Start完成了一个脚本的初始化。
- OnApplicationPause方法,检测到暂停状态时,会在当前帧结束后调用本方法 。
- Update(每帧,比如用来角色移动)、LateUpdate(每帧,比如渲染前移动相机,在Update之后调用)、FixedUpdate(定时器更新,比如给刚体定时加动力)
协程。由于脚本是单线程的。于是引入通过C#语言的迭代器实现的协程。一般在
Update
返回时执行。using System.Collections; using System.Collections.Generic; using UnityEngine; //MonoBehaviour挂载到游戏对象身上时类名和文件名需要一致 public class ParentBehaviourScript : MonoBehaviour { private IEnumerator WaitAndPrint(float waitTime) { //System.Console.WriteLine 只输出到Editor.log日志文件 //System.Console.WriteLine("start WaitAndPrint: {0}", waitTime); //继承MonoBehaviour可使用print, 日志文件和窗口都有输出 print(Time.time + ":Call WaitAndPrint"); //如果yield返回WaitForSeconds,根据时间算出挂起帧数 yield return new WaitForSeconds(waitTime); print(Time.time + ":Done WaitAndPrint"); } private IEnumerator TestWWW(string url) { print(Time.time + ":Call TestWWW"); //如果yield返回的WWW对象,那么在完成加载后再唤醒此协程 WWW www = new WWW(url); yield return www; print(Time.time + ":Done TestWWW"); } // Use this for initialization IEnumerator Start ()// 这个的返回值已经变化为IEnumerator,不是默认的void { //Debug.Log, 日志文件和窗口都有输出,即使不继承MonoBehaviour也可用 Debug.Log(Time.time + ":Start be called First Time"); //启动一个协程但不挂起自己和不等待他执行完成 StartCoroutine(TestWWW("https://www.baidu.com")); //yield返回一个协程,挂起自己,启动协程并等他执行完后唤醒自己 yield return StartCoroutine(WaitAndPrint(2)); print(Time.time + ":Done Start"); } void ApplyDamage(float damage) { Debug.Log("ApplyDamage be called:" + damage); } // Update is called once per frame void Update () { //通过广播调用自己及所有子对象脚本的ApplyDamage方法 //BroadcastMessage("ApplyDamage", 5.0f); } }
- xx
- yy
评论 (0)