Unity脚本开发基础(摘要)
创建并运行脚本:
unity 使用 C# 和 JavaScript 作为脚本语言,在创建一个脚本时会自动创建 Start 和 Update 两个常用函数。Unity 中会有些特定的函数,这些特定的函数在一定条件下会被调用,称为必然事件(Certain Events)
名称 | 触发条件 | 用途 |
---|---|---|
Awake | 脚本实例被创建时调用 | 用于游戏对象的初始化,注意Awake的执行早于所有的 Start 脚本 |
Start | Update函数第一次运行之前调用 | 用于游戏对象的初始化 |
Update | 每帧调用一次 | 用于更新游戏场景和状态(和物理状态有关的更新应该放在FixedUpdate里) |
FixedUpdate | 每个固定物理时间间隔(Physics Time Step)调用一次 | 用于物理状态的更新 |
LateUpdate | 每帧调用一次(在Update调用之后) | 用于更新游戏场景和状态,和相机有关的更新一般放在这里FixedUpdate里) |
Awake 早于 Start 调用,Awake在MonoBehavior创建后就立刻调用,Start将在MonoBehavior创建后在该帧Update之前,在该Monobehavior.enabled == true的情况下执行。
在Update 中尽量不要使用耗时过高的函数(例如 GetComponent),因为这样会大大减少程序的运行效率。如果要使用 GetComponent,应该在初始化的时候把组件的引用保存在变量中。
在Unity中,开发者编写的每一个脚本都被视为一个自定义组件(Component),游戏对象可以理解为容纳各个组件的容器,所以可以通过 Add Component 来将脚本添加到对象中。
首先创建一个脚本,Assets -> Create -> C# Script 命令,命名为 HelloWorld,在Start 函数中填加以下语句
Debug.Log("Hello World!");//输出Hello World 到 Console 视图
脚本本身只是一个组件,是无法脱离游戏对象独立运行的,它必须添加到游戏对象上才会生效。
依次选择菜单栏中的 GameObject ->Create Empty 命令即可创建一个空游戏对象。再 Inspector 视图中单击对象属性下方的 Add Component 按钮,在弹出的菜单中依次打开 Scripts -> HelloWorld。这样就将HelloWorld脚本绑定到新建的游戏对象中。也可以在 Project 视图中将 HelloWorld 脚本直接拖动到 Inspector 视图中的 GameObject 对象上来完成绑定操作。
按下播放按钮,会在 Console 视图中输出 “Hello World!”,如果用户当前编辑器页面没有 Console 视图,可以通过 【Ctrl+Alt+C】组合键的方式把该视图显示出来。
在 Start 函数中输出只会输出一句 “Hello World!”,而如果将上述语句加入到 Update 中,将会每帧输出一次。
访问游戏对象和组件:
MonoBehaviour 类
Unity中的脚本都是继承自MonoBehaviour,它定义了基本的脚本行为,必然事件也是从 MonoBehaviour 继承而来。除了必然事件, MonoBehaviour还定义了对各种特定事件(例如模型碰撞、鼠标移动)的响应函数,这些函数均以 On 作为开头。
常用事件响应函数:
名称 | 用途 |
---|---|
OnMouseEnter | 鼠标移入GUI控件或者碰撞体时调用 |
OnMouseOver | 鼠标停留在GUI控件或者碰撞体时调用 |
OnMouseExit | 鼠标移出GUI控件或者碰撞体时调用 |
OnMouseDown | 鼠标在GUI控件或者碰撞体上按下时调用 |
OnMouseUp | 鼠标按键释放时调用 |
OnTriggerEnter | 当其他碰撞体进入触发器时调用 |
OnTriggerExit | 当其他碰撞体离开触发器时调用 |
OnTriggerStay | 当其他碰撞体停留在触发器时调用 |
OnCollisionEnter | 当碰撞体或者刚体与其他碰撞体或者刚体接触时调用 |
OnCollisionExit | 当碰撞体或者刚体与其他碰撞体或者刚体停止接触时调用 |
OnCollisionStay | 当碰撞体或者刚体与其他碰撞体或者刚体保持接触时调用 |
OnControllerColliderHit | 当控制器移动时与碰撞体发生碰撞时调用 |
OnBecameVisible | 对于任意一个相机可见时调用 |
OnBecameInvisible | 对于任意一个相机不可见时调用 |
OnEnable | 对象启用或者激活时调用 |
OnDisable | 对象禁用或者取消激活时调用 |
OnDestroy | 脚本销毁时调用 |
OnGUI | 渲染GUI和处理GUI消息时调用 |
访问游戏对象:
1.通过名称查找:
GameObject.Find() 如果场景中存在指定名称的游戏对象,那么返回该对象的引用,否则返回 null。如果存在多个游戏对象使用同一名称,那么返回第一个对象的引用。第一个的含义是在 Hierarchy 中排列顺序第一个,而不是创建顺序。
GameObject player;
palyer = GameObject.Find("player");
2.通过标签查找 :
GameObject.FindWithTag() 如果场景中存在指定标签的游戏对象,那么返回该对象的引用
如果想要获取全部相同标签的对象,可以通过 FindGameObjectsWithTag() 方法
GameObject player;
GameObject[] enemies;
palyer = GameObject.FindWithTag("player");
enemies = GameObject.FindGameObjectsWithTag("Enemy");
访问组件:
在Unity中脚本可以被认为是用户自定义的组件,并且可以添加到游戏对象上来控制游戏对象的行为,而游戏对象则可视为容纳各种组件的容器。
对于系统内置的常用组件,Unity 提供了非常便捷的访问方式,只需要在脚本里直接访问组件对应的成员变量即可,这些成员变量定义在 MonoBehaviour 中并被脚本继承了下来。
常用组件及其变量:
组件名称 | 变量名 | 组件作用 |
---|---|---|
Transform | transform | 设置对象位置、旋转、缩放 |
Rigibody | rigibody | 设置物理引擎的刚体属性 |
Renderer | renderer | 渲染物体模型 |
Light | light | 设置灯光属性 |
Camera | camera | 设置相机属性 |
Collider | collider | 设置碰撞体属性 |
Animation | animation | 设置动画属性 |
Audio | audio | 设置声音属性 |
如果游戏对象上不存在某组件,则该组件对应变量的值将为空值(null)
如果要访问的组件不属于上表中的常用组件,或者访问的是游戏对象上的脚本,可以通过一下函数得到组件的引用
函数名 | 作用 |
---|---|
GetComponent | 得到组件 |
GetComponents | 得到组件列表(用于有多个同类型组件的时候) |
GetComponentlnChildren | 得到对象或对象子物体上的组件 |
GetComponentslnChildren | 得到对象或对象子物体上的组件列表 |
再次强调,GetComponent 比较耗时,因此尽量避免在 Update 中调用这些获取组件的函数,而是应该在初始化时把组件的引用保存在变量中。
简单示例:
Example script = GetComponent<Example>();//得到游戏对象上的 Example 脚本组件
Transform t = GetComponent<Transform>(); //得到游戏对象上的 Transform 组件
**除了用函数获取外, Unity还有一种非常便捷访问组件或游戏对象的方法,通过声明访问权限为 Public 的变量然后将要访问的组件或者对象赋值给该变量,就可以在脚本中通过变量访问组件或对象了。
(1)在脚本中添加类型分别为 GameObject 和 Transform 的两个成员变量,访问权限设置为 Public,示例代码如下:
using UnityEngine;
using System.Collections;
public class Hello : MonoBehaviour {
public GameObject cube;
public Transform sphereTransform;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
}
(2)保存脚本,查看 Player 游戏对象的Inspector视图,可以看到Hello脚本的视图参数添加了两项,正是刚才添加的两个成员变量,目前没有对其赋值,所以变量的值均显示为 None。
(3)用鼠标左键在 Hierarchy 视图中将Cube游戏对象拖到 Inspector 视图 Cube参数上,接着拖动sphere游戏对象到 Inspector视图的 Sphere Transform 参数上,完成对两个成员变量的赋值。
此时Hello 脚本的两个成员变量分别保存了 Cube 对象的引用和 Sphere 对象的 Transform 组件引用,这样在脚本中访问两个成员变量即可。
常用脚本API
Transform 组件:
transform组件控制游戏对象在Unity场景中的位置、旋转和大小比例,每个游戏对象都包含一个 Transform 组件。在游戏中如果想要更新玩家位置,设置相机观察角度都免不了要和Transform组件打交道。
Transform 组件的成员变量:
成员变量 | 说明 |
---|---|
position | 世界坐标系中的位置 |
localPosition | 父对象局部坐标系中的位置 |
eulerAngles | 世界坐标系中以欧拉角表示的旋转 |
localEulerAngles | 父对象局部坐标系中的欧拉角 |
right | 对象在世界坐标系中的右方向 |
up | 对象在世界坐标系中的上方向 |
forward | 对象在世界坐标系中的前方向 |
rotation | 世界坐标系中以四元数表示的旋转 |
localRotation | 父对象局部坐标系中以四元数表示的旋转 |
localScale | 父对象局部坐标系中的缩放比例 |
parent | 父对象的Transform 组件 |
worldToLocalMatrix | 世界坐标系到局部坐标系的变换矩阵 (只读) |
localToWorldMatrix | 局部坐标系到世界坐标系的变换矩阵(只读) |
root | 对象层次关系中根对象的 Transform组件 |
childCount | 子孙对象的数量 |
lossyScale | 全局缩放比例(只读) |
Transform组件的成员函数:
成员函数 | 说明 |
---|---|
Translate | 按指定的方向和距离移动 |
Rotate | 按指定的欧拉角旋转 |
RotateAround | 按给定旋转轴和欧拉角进行旋转 |
LookAt | 旋转是的自身的前方巷指向目标的位置 |
TransformDirection | 将一个方向从局部坐标系变换到世界坐标系 |
InverseTransformDirection | 讲一个方向从世界坐标系变换到局部坐标系 |
TransformPoint | 将一个位置从局部坐标系变换到世界坐标系 |
InverseTransformPoint | 将一个位置从世界坐标系转换到局部坐标系 |
DetachChildren | 与所有子物体解除父子关系 |
Find | 按名称查找子对象 |
IsChildOf | 判断是否是指定对象的子对象 |
Time 类
在 Unity 中可以通过 Time 类来获取和时间有关的信息,可以用来计算帧速率,调整时间流逝速度等功能。Time 类包含了一个重要的类变量 deltaTime,他表示距上一次调用所用的时间。
Time类成员变量:
成员函数 | 说明 |
---|---|
time | 游戏从开始到现在经理的时间(秒)(只读) |
timeSinceLevelLoad | 此帧的开始时间(秒)(只读),从辞官加载完成开始计算 |
deltaTime | 上一帧耗费的时间(秒)(只读) |
fixedTime | 最近FixedUpdate的时间。该时间从游戏开始计算 |
fixedDeltaTime | 物理引擎和FixedUpdate的更新时间间隔 |
maximumDeltaTime | 一帧的最大耗费时间 |
smoothDeltaTime | Time.deltaTime的平滑淡出 |
timeScale | 时间流逝速度的比例。可用来制作慢动作特效 |
frameCount | 已渲染的帧的总数(只读) |
realtimeSinceStartup | 游戏从开始到现在经理的真实时间(秒),改时间不会受timeScale影响 |
captureFramerate | 固定帧率设置 |
Random类:
Random类可以用来生成随机数。
Random类的成员变量:
成员变量 | 说明 |
---|---|
seed | 随机数生成器种子 |
value | 返回一个0~1之间的随机浮点数,包含 0 和 1 |
insideUnitSphere | 返回位域半径为1的求体内的一个随机点 |
insideUnitCircle | 返回位域半径为1的圆内的一个随机点(只读) |
onUnitSphere | 返回半径为1的球面上的一个随机点(只读) |
rotation | 返回一个随机旋转(只读) |
rotationUniform | 返回一个均匀分布的随机旋转(只读) |
Random类的成员变量:
成员函数 | 说明 |
---|---|
Range | 返回 min 和 max 之间的一个随机浮点数,包含 min 和 max |
Mathf类
Mathf类的变量:
变量 | 说明 |
---|---|
PI | 圆周率π,即3.14159265358979...(只读) |
Infinity | 正无穷大 ∞(只读) |
NegativeInfinity | 负无穷大 - ∞ (只读) |
Deg2Rad | 度到弧度的转换系数(只读) |
Rad2Deg | 弧度到度的转换系数(只读) |
Epsilon | 一个很小的浮点数(只读) |
Mathf类的常用方法:.
常用方法 | 说明 |
---|---|
Sin | 计算角度(单位为弧度)的正弦值 |
Cos | 计算角度(单位为弧度)的余弦值 |
Tan | 计算角度(单位为弧度)的正切值 |
Asin | 计算反正弦值(返回的角度值单位为弧度) |
Acos | 计算反余弦值(返回的角度值单位为弧度) |
Atan | 计算反正切值(返回的角度值单位为弧度) |
Sqrt | 计算平方根 |
Abs | 计算绝对值 |
Min | 返回若干数值中的最小值 |
Max | 返回若干数值中的最大值 |
Pow | Pow(f,p)返回 f 的 p 次方 |
Exp | Exp(p)返回 e 的 p 次方 |
Log | 计算对数 |
Log10 | 计算基为10的对数 |
Ceil | Ceil(f)返回大于或等于 f 的最小整数 |
Floor | Floor(f)返回小于或等于f的最大整数 |
Round | Round(f)返回浮点数 f 进行四舍五入后得到的整数 |
Clamp | 将数值限制在 min 和 max 之间 |
Clamp01 | 将数值限制在 0 和 1 之间 |
Coroutine协同程序
Coroutine也称为协同程序或者协程,协同程序可以和主线程并行运行,和多线程有些类似。协同程序可以用来实现让一段程序等待一段时间后继续运行的效果。
与协同程序有关的函数:
函数 | 说明 |
---|---|
StartCoroutine | 启动一个协同程序 |
StopCoroutine | 中指一个协同程序 |
StopAllCoroutines | 中指所有协同程序 |
WaitForSeconds | 等待若干秒 |
WaitForFixedUpdate | 等待直到下一次 FixedUpdate调用 |
C#协程例子:
using UnityEngine;
using System.Collections;
public class Hello : MonoBehaviour {
// Use this for initialization
IEnumerator Start () {
Debug.Log ("Starting " + Time.time);
yield return StartCoroutine(WaitAndPrint());//启动协同程序 WaitAndPrint
print("Done " + Time.time);
}
IEnumerator WaitAndPrint(){
yield return new WaitForSeconds (5f);
print ("WaitAndPrint " + Time.time);
}
}
在C#中,协同程序的返回类型必须为 IEnumerator ,yield 要用 yield return 代替,并且启动协同程序要用 StartCoroutine 函数。