Unity笔记——1.Unity3D脚本基础

Unity3D脚本基础

Unity3D的脚本后端Mono与IL2CPP

Unity的脚本后端我们可以选择使用Mono或者IL2CPP,可以到Edit | Project Settings | Player | Configure | Scripting Backend中进行选择

ScriptingBackend

Mono

Mono是Xamarin公司的开源项目,是基于CLI通用语言架构以及C#的ECMA标准的.NET框架另外一种实现,可以分为四个部分:C#编译器 mcs、Mono运行时、基础类库、Mono类库

C# 编译器 mcs

mcs是自Mono2.11版本之后的统一编译器,因为mcs是使用C#编写的编译器,使用了很多 .Net API,所以在使用mcs时需要Mono运行时来运行mcs,在win平台可以使用微软的.Net运行时,也可以使用Mono运行时

Mono运行时

Mono运行时实现了ECMA的通用语言架构标准,定义了.NEt框架基础结构的可执行代码以及代码的运行时环境,提供了一个JIT编译器、一个AOT编译器,同时还有类库加载器、GC、线程系统等

基础类库

Mono提供了广泛的基础类库并且与微软的.Net框架兼容

Mono类库

Mono还提供了超越.Net框架之外的诸多类

使用Mono脚本后端的编译过程

我们用C#编写的游戏脚本会通过Mono mcs编译器编译成通用中间语言CIL(CIL字节码Byte Code,类似于Java字节码),之后CIL字节码再通过Mono运行时的JIT或者AOT编译器转译为本地代码Native Code

  • JIT编译器

JIT,即时编译或者称动态编译,是指在程序执行时才编译代码,解释一条语句执行一条语句,即翻译一条中间语言成机器代码,然后执行该条机器代码,Android的Dalvik虚拟机就是使用的JIT编译,而IOS平台则不允许这样的动态编译

  • AOT编译器

代码在程序运行之前就已经编译好了,不过在AOT中部分代码也会通过JIT方式来动态编译,在IOS平台上Unity会使用Full AOT来进行编译,集中所有的IL中间代码不适用JIT,直接进行AOT编译生成一个本地代码镜像,在运行时直接加载镜像

IL2CPP

IL2CPP用于将由C#编译器编译生成的CIL字节码直接转换为本地C++代码,之后再由目标平台的C++ compiler编译出本地代码Native Code,这样应用程序可以更快的运行本地代码,从而提升性能;IL2CPP有自己的AOT编译器和VM,并且允许定制对GC等其他子系统和编译过程的改进

IL2CPP AOT编译器

il2cpp-toolchain-smaller

IL2CPP AOT编译器用于将IL中间语言转换为C++代码,其可执行文件的名字叫做il2cpp.exe,可以在Unity的安装目录EditorDatail2cpp下找到,il2cpp.exe是一个托管代码可执行文件,是由C#编写

使用IL2CPP脚本后端编译的过程:

IL2CPP-3

我们使用C#编写的游戏逻辑会通过Unity自带的Mono mcs编译器编译成的IL中间语言,IL和其他程序集一起组成托管程序集

无用代码的剥离,来减小构建游戏的大小,包括托管代码的剥离、原生代码的剥离

  • 托管代码的剥离,UnityLinker会通过中间语言移除掉没有使用的类型(未使用的类、结构体等,包括已使用类,但是并没使用的类的方法),可以在Player Setting中的Stripping Level选项选择Strip Assemblies开启,需要注意的是,这个选项只有在使用Mono脚本后端可选,在使用IL2CPP时是默认开启的

  • 原生代码剥离,移除原生的Unity引擎代码中未使用的模块和类,可以在Player Setting中Strip Engine Code选项选择开启,禁用的话会保留原生Unity引擎代码中所有的模块和类

il2cpp.exe将剥离之后的托管程序集转换成标准C++代码,之后再传递给最终的目标平台对应的编译器编译生成的C++代码和IL2CPP的运行库,最终根据目标平台将代码链接到Dll或者可执行文件中。

IL2CPP 虚拟机VM运行时库

IL2CPP 运行时库用于支持IL2CPP虚拟机的运行,提供如GC、线程等支持,运行库的名字叫做libil2cpp,该运行时库最终其会作为一个静态库链接到用户可执行应用中,这样做的好处是简单可移植

Unity3D中的引用类型

UnityEngine.Object类

在Unity3D的脚本系统中,Unity使用命名空间UnityEngine来盛放Unity3D定义的类型;
其中UnityEngine.Object类是最基本的类,是在Unity3D中所有对象的基类;
所有派生自UnityEngine.Object类的公共变量都会被显示在监视面板中,Unity程序员可通过编辑器来修改这些变量的数值。

UnityEngine.Object类提供的类成员:

字段:

  • hideFlags:标识该游戏对象是否被隐藏
  • name

公共方法:

  • GetInstanceID
  • ToString:返回该游戏对象的名称

静态方法:

  • Destory
  • DestoryImmediate
  • DontDestoryOnLoad
  • FindObjectOfType
  • FindObjectsOfType
  • Instance

UnityEngine.Component类

除了最基本的UnityEngine类之外,另一个很重要的类是派生自UnityEngine.Object类的UnityEngine.Component类。它是所有能添加到游戏对象GameObject上的组件Component的基类。

UnityEngine.Component类提供的类成员:

字段:

  • gameObejct:该组件所在的游戏对象
  • tag:该组件所在游戏对象的标签
  • transform:该组件所在游戏对象上的Transform组件

公共方法:

  • BroadcastMessage
  • CompareTag:返回该对象是否被标签标记
  • GetComponent
  • GetComponentInChildren
  • GetComponentInParent
  • GetComponents
  • GetComponentsInChildren
  • GetComponentsInParent
  • SendMessage
  • SendMessageUpwards

UnityEngine.Behaviour类

UnityEngine.Behaviour类继承自UnityEngine.Component类,
是一个可以启用或者禁用的组件

UnityEngine.Behaviour类提供的类成员:

变量:

  • enable:启用状态下,会执行每帧的更新,禁用状态不会被执行
  • isActiveAndEnable:表示当前Behaviour是否被启用

UnityEngine.MonoBehaviour类

UnityEngine.MonoBehaviour继承自UnityEngine.Behaviour类;在Unity3D游戏引擎中,UnityEngine.MonoBehaviour类是所有Unity3D脚本的基类。

UnityEngine.MonoBehaviour类提供的类成员:

消息:

  • Awake
  • Start
  • Update
  • LateUpdate
  • FixedUpdate
  • OnEnable
  • OnDisable
  • OnDestory
  • OnBecameInvisible
  • OnBecameVisible
  • OnCollisionEnter
  • OnCollsionExit
  • OnCollisionStay
  • OnGUI
  • OnLevelWasLoaded
  • OnMouseDown
  • OnMouseDrag
  • OnMouseEnter
  • OnMouseExit
  • OnMouseOver
  • OnMouseUp
  • OnMouseUpAsButton
  • OnTriggerEnter
  • OnTriggerExit
  • OnTriggerStay
  • OnValidate
  • Reset

公共方法:

  • CancelInvoke
  • Invoke
  • InvokeRepeating
  • IsInvoking
  • StartCoroutine
  • StopAllCoroutine
  • StopCoroutine

Unity3D脚本编程时需要注意,在C#中使用new操作符来实例化引用类型,但是在Unity3D中编写脚本时,凡是继承自MonoBehaviour类的类型包括MonoBehaviour本身都无法使用new关键字来进行实例化;
在Unity3D中我们可以通过将脚本以组件的形式挂载在游戏对象上来实现创建类型对象的目的。
当然,不需要继承自MonoBehaviour类的类型,是可以通过new操作符实例化的。

Unity3D中的值类型

向量结构

Vector2、Vector3、Vector4这三个结构体分别用来表示二维、三维、四维向量。

向量结构的实例成员:

  • magnitude
  • normalized
  • sqrMagnitude
  • x
  • y
  • z
  • w

向量结构的方法:

  • Cross
  • Dot
  • Distance
  • Lerp

向量计算

向量之间的乘法与标量之间的乘法不同,向量的乘法常用的有两种

  • 点乘dot product(或者称点积、内积inner product)
  • 叉乘cross product(或者称叉积、外积outer product)
向量之间的点乘

向量a(ax,ay,az)与向量b(bx,by,bz)为示例

向量点乘公式一:
将两个三位向量的对应分量相乘后求和就是这两个向量点乘的结果为一个标量

a·b = axbx + ayby + azbz
向量点乘的几何意义

vectorproduct

即我们可以通过两个向量点积结果的符号来判断两个向量方向的关系
a·b > 0时,两个向量方向相同
a·b = 0时,两个向量相互垂直
a·b < 0时,两个向量方向相反

向量a与向量b,点乘的结果可以看作,向量b在向量a所处单位向量方向上的投影长度乘以向量a的模

向量点乘的一些性质
(k a)·b = a·(k b) = k(a·b) k为标量

a·(b+c) = a·b + a·c 减法同理

a·a = axax + ayay + azaz = |a|2 可以利用点积来求一个向量的模或者直接比较两个向量与自身的点积a·a与b·b的大小

向量点乘公式二:
当两个向量都是单位向量时:

dotproductcos

单位向量a与单位向量b点乘的结果为它们夹角的余弦乘以|b|,即夹角余弦值

由此,可推导出向量a与向量点乘的公式为:

a·b = |a||b|cos<a,b>

向量之间的叉乘

a X b =(ax,ay,az) X (bx,by,bz)
=(aybz-azby, azbx-axbz,axby-aybx)

向量叉乘的结果是一个新的向量,该新向量的模为,向量a与向量b模的乘积再乘以他们之间夹角的正弦值:
|a X b| = |a||b|sin<a,b>
新向量的方向根据我们使用的左手坐标系或者右手坐标系确定
crossProduct

当两个向量平行即方向相同或者相反时,叉乘结果为零向量:
a X b = 0

其他值类型

  • Color
  • Color32
  • Ray
  • Touch
  • RaycastHit
  • Bounds
  • Rect
  • Plane

REF

书籍:
Unity3D脚本编程

博客:
https://blogs.unity3d.com/2015/05/06/an-introduction-to-ilcpp-internals/

原文地址:https://www.cnblogs.com/sylvan/p/8834947.html