首页 > 代码库 > Unity3D 之 C# 脚本

Unity3D 之 C# 脚本

引用类型 :class ,interface, 数组 , delegate , object ,string (object 是C#中所有类型,包括所有的值类型和引用类型的根类,string 类型是一个从object类直接继承的密封类型(不能再被继承),其实例表示Unicode字符串)

try后面一个finally,try中有一个return,那么finally中的代码会不会运行?如果运行,是在return后还是return前答:会运行,并且在return 后运行。

public static const int A=1;这段代码有错误么?是什么? —— const成员都是static所以应该去掉static


谈谈final,finally,finalize的区别
   防止重写,
   try{}catch{}
   在垃圾回收之前,尝试释放资源并执行其他清理操作

const和static readonly 区别是什么?
   编译时常量
   运行时常量


net中什么类不能被继承?答:如果在类前加上sealed关键字,则表示该类为密封类,密封类不能被继承。sealed 除了可以应用于类外,还可以应用于实例方法和属性。密封方法会重写基类中的方法,但其本身不能在任何派生类中进一步重写。当应用于方法或属性时,sealed 修饰符必须始终与override一起使用

C#支持多重继承么?—— 不支持。可以用接口来实现。

私有成员会被继承么?—— 会,但是不能被访问。所以看上去他们似乎是不能被继承的,但实际上确实被继承了。

被virtual修饰的方法可以被子类覆写。

能够实现允许某个类被继承,但不允许其中的某个方法被覆写么?—— 可以,标记这个类为public,并标记这个方法为sealed。

为什么不能指定接口中方法的修饰符?—— 接口中的方法用来定义对象之间通信的契约,指定接口中的方法为私有或保护没有意义。他们默认为公有方法。接口中所有方法必须是抽象的,并且不能指定方法的访问修饰符。抽象类中可以有方法的实现,也可以指定方法的访问修饰符。

 


 

String/StringBuilder的异同

string是一个不可变的数据类型,一旦对字符串对象进行了初始化,该字符串对象就不能改变了。修改字符串内容的方法

和运算符实际上是创建一个新的字符串.

stringbuilder分配好内存,对字符串的修改就在赋予stringbuilder实例的存储单元中进行.str=null,声明而不分内存空间,str=""声明而分内存空间

String s = new String("xyz");创建了几个String Object? —— 两个对象,一个是“xyx”,一个是指向“xyx”的引用对像s


协同程序,即在主程序运行时同时开启另一段逻辑处理,来协同当前程序的执行。换句话说,开启协同程序就是开启一个线程。

在Unity3D中,使用MonoBehaviour.StartCoroutine方法即可开启一个协同程序,也就是说该方法必须在MonoBehaviour或继承于MonoBehaviour的类中调用。

       在Unity3D中,使用StartCoroutine(string methodName)和StartCoroutine(IEnumerator routine)都可以开启一个线程。区别在于使用字符串作为参数可以开启线程并在线程结束前终止线程,相反使用IEnumerator 作为参数只能等待线程的结束而不能随时终止(除非使用StopAllCoroutines()方法);另外使用字符串作为参数时,开启线程时最多只能传递一个参数,并且性能消耗会更大一点,而使用IEnumerator 作为参数则没有这个限制。

        在Unity3D中,使用StopCoroutine(string methodName)来终止一个协同程序,使用StopAllCoroutines()来终止所有可以终止的协同程序,但这两个方法都只能终止该MonoBehaviour中的协同程序。协同程序的返回类型为Coroutine类型。在Unity3D中,Coroutine类继承于YieldInstruction,所以,协同程序的返回类型只能为null、等待的帧数(frame)以及等待的时间。


Unity是不支持多线程的,也就是说我们必须要在主线程中操作它,可是Unity可以同时创建很多脚本,并且可以分别绑定在不同的游戏对象身上

每个脚本的Awake、Update、LateUpdate、FixedUpdate等等,方法在后台都有一个总汇。

后台的Awake()

{

       脚本0中的Awake();

       脚本1中的Awake();

       脚本2中的Awake();

}

       后台的方法 Awake、Update、LateUpdate、FixedUpdate等等都是按照顺序,等所有子脚本中的Awake执行完毕后在去执行 Start 、Update、LateUpdate等等。所以这里也就解释了Unity没有多线程的概念。

在脚本2的Awake方法中创建一个立方体对象。在脚本0的Awake方法中去获取这个立方体对象。如果脚本的执行顺序是 先执行Script2 然后在执行Script0那么Script0中的Awake就可以获取到该立方体对象,可是如果脚本的执行顺序是先Script0然后在Script2,那么Script0肯定会报空指针错误的。

          那么实际项目中的脚本会非常非常多,他们的先后顺序我们谁也不知道。所以我的建议一般在Awake方法中创建游戏对象或在Resources.Load(Prefab) 对象。在Start方法中去获取游戏对象,或者游戏组件,这样就可以确保万无一失了。

     如果说你非要控制脚本的执行先后顺序,也不是完全不行!Unity可以设置脚本执行的顺序。如下图所示,选择任意脚本在Inspector视图中点击Execution Order..按钮。点击右下角的“+”将弹出下拉窗口,包括游戏中的所有脚本。添加脚本完毕后,Default Time下方数值越小的排在越前面脚本将率先执行,如果没有设置的脚本将按默认的顺序执行。


Unity 脚本的生命周期

Update —— 正常更新,用于更新逻辑,此方法每帧都会由系统自动调用一次

LateUpdate —— 推迟更新,此方法在Update方法执行完后调用,同样每一帧都调用

Awake —— 脚本唤醒,为系统执行的第一个方法,用于脚本的初始化,在脚本的生命周期中只执行一次

FixedUpdate —— 固定更新,设置更新频率

Start —— 在Awake方法之后,Update方法执行之前执行,并且只执行一次

OnDestroy —— 当前脚本销毁时使用

使用脚本调用游戏对象 —— 将脚本绑定在一个游戏对象身上,也可以在代码中动态绑定脚本和删除脚本。任何一个游戏对象都可以同时绑定多条游戏脚本,并且这些脚本互不干涉,各自完成自己的生命周期

GameObject.CreatePrimitive —— 用于创建一个原始游戏对象,其参数可设置为立方体,球体,圆柱体等系统默认提供的游戏对象

AddComponet —— 用于给游戏对象添加组件

renderer.material.color —— 设置渲染材质的颜色或者贴图

transform.position —— 设置该游戏对象的位置

 


 

获取游戏对象:

通过对象名称获取对象 —— 使用Find 方法传入对象的完整路径名称即可在代码中获取游戏对象

通过标签获取单个游戏对象 —— “Add Tag ”中 Element 0 选项右侧直接输入标签名称即可添加新标签 FindWithTag() —— FindWithTag 方法只能获取一个游戏对象,如果程序中多个对象都添加了同样的标签,那么这个方法只能获取第一个添加此标签的对象

通过标签获取多个游戏对象 —— FindGameObjectsWithTag() 方法并将相应的标签名称作为参数传入,即可返回一个游戏对象数组

添加组件与修改组件

添加游戏组件时,可以使用AddComponent()方法,由于组件自身没有对应的删除方法,需要使用父类执行Object.Destroy()

render.material 引用当前脚本绑定对象的材质,直接为其赋值即可修改对象材质

一个游戏对象可以绑定多条脚本,实现这些脚本之间的交互就可以使用广播机制

     游戏对象之间发送的广播与消息大致分为:

1,向子对象发送,将发送至该对象的同辈对象或者子孙对象中;

        gameObject.BroadcastMessage("ReceiveBroadcastMessage","A0---BroadcastMessage()");

         接受父类发送的消息:

         function ReceiveBroadcastMessage(str: String)

         { Debug.Log(); }

2,给自己发送,发送至自身对象;

         gameObect.SendMessage();

3,向父对象发送,发送至该对象的同辈或者父辈对象中

         gameObject.SendMessageUpwards();

克隆游戏对象        Instantiate()

动态地为某个游戏对象添加脚本组件 ——  AddComponent(),将脚本的名称作为参数传入即可完成脚本组件的添加

obj.transform.position 引用得到obj游戏对象在三维坐标系中的位置,存储在Vector3容器中(保存着xyz轴的坐标)

         transform.Rotate() —— 用于设置模型绕自身旋转,参数为旋转的速度与旋转的方向

         transform.RotateAround() —— 用于设置模型围绕某一个点旋转

         Time.deltaTime —— 用于记录上一帧所消耗的时间,用作模型旋转的速度系数

         Vector3.right —— x轴方向

         Vector3.up —— y轴方向

         Vector3.forward —— z轴方向

transform.Translate() 唯一参数为平移模型的方向    obj.transform.Translate(Vector3.forward * Time.deltaTime)


命名规则 —— 必须与项目资源视图中该脚本的名称对应,否则无法成功绑定至游戏对象

Unity3D     工具类

Time —— 获取当前的系统时间

     Time.time —— 从游戏开始后计时开始,表示截至目前共运行的游戏时间

     Time.deltaTime —— 获取Update() 方法中完成上一帧所消耗的时间

     Time.fixedTime —— FixedUpdate() 方法中固定消耗的时间总和

使用 WaitForSeconds() 方法可以以秒为单位让程序等待一段时间,此方法可直接使游戏主线程进入等待状态。该方法的返回值为IEnumerator类型,在需要等待的地方 调用 yield return new WaitForSeconds(2)

Unity中所有用到的模型旋转的,底层都是由四元数实现,可以精确计算模型的旋转的角度

Unity3D 之 C# 脚本