
3.8 脚本
3.8.1 基本介绍
Unity3D是基于Mono项目实现的,而Mono项目可以简单理解为第三方实现的跨平台的.net framework。
因此,个人推荐开发Unity3D使用C#脚本而不是Javascript脚本。一方面Unity3D的C#资源远比Javascript资源多;另外,一些不常见的问题,可以直接查微软的.net的帮助,很多情况下都能通用。
在这里,不介绍C#语言的基础了,大家可以直接查微软的资料,基本数据类型、语法、类的操作等不变。这里只介绍与微软C#不同的地方。
在“Assets”里右击,选择“Create”→“C# Script”就可以添加脚本组件,如图3-52所示。

图3-52
3.8.2 MonoBehaviour
一个脚本想要成为组件,必须继承MonoBehaviour类。
之后,公开属性的定义,除了可以在代码中定义,在Unity3D里,公开属性可以在Unity编辑界面中定义。
例:新建脚本test.cs
using UnityEngine; using System.Collections; public class test : MonoBehaviour { public string str; public GameObject go; // Use this for initialization void Start () { } }
新建一个游戏对象,将脚本拖到该游戏对象下成为其组件,如图3-53所示。

图3-53
这时,可以直接在组件上定义公开属性的值,如“str”;也可以通过拖动,将其他对象作为公开属性的值,如“go”,如图3-54所示。

图3-54
3.8.3 Transform
Transform属性可以用来设置游戏对象的位置、角度和缩放,等同于在编辑界面修改Transform的值。
(1)设置游戏对象位置
设置对象的transform.position属性即可。
代码:
this.transform.position = new Vector3 (1f, 2f, 3f);
等效于在编辑器中直接修改position的值,如图3-55所示。

图3-55
(2)设置游戏对象角度
调用对象的transform.Rotate方法。
代码:
transform.Rotate (new Vector3 (15f, 45f, 90f));
等效于在编辑器中修改rotation的值,如图3-56所示。

图3-56
(3)设置游戏对象的大小
设置对象的transform.localScale属性即可。
代码:
transform.localScale = new Vector3 (1.5f, 2f, 3f);
等效于在编辑器中修改scale的值,如图3-57所示。

图3-57
3.8.4 GameObject
GameObject用来控制游戏对象本身,最常用的方法是启用或者禁用游戏对象。
代码:
gameObject.SetActive(false);
等效于在编辑界面操作,就是Cube选项选中或者不选中,分别对应启用和禁用两种状态,如图3-58所示。

图3-58
3.8.5 常用事件
1. Awake
这个函数总是在任何Start()函数之前一个预设被实例化之后被调用,如果一个GameObject是非激活的(inactive),在启动期间Awake函数是不会被调用的,直到它是活动的(active)。
2. OnEnable
只有在对象是激活(active)状态下才会被调用,这个函数只有在Object被启用(enable)后才会调用。这会发生在一个MonoBehaviour实例被创建,例如当一个关卡被加载或者一个带有脚本组件的GameObject被实例化。
3. Start
只要脚本实例被启用了Start()函数,将会在Update()函数第一帧之前被调用。
4. FixedUpdate
FixedUpdate函数会比Update函数更频繁地被调用。它一帧会被调用多次,但它很少在帧之间被调用。所有的图形计算和更新在FixedUpdate之后会立即执行。当在FixedUpdate里执行移动计算,你并不需要Time.deltaTime乘以你的值,这是因为FixedUpdate是按真实时间,独立于帧率被调用的。
5. Update
Update每一帧都会被调用,对于帧更新它是主要的负荷函数。
6. LateUpdate
LateUpdate会在Update结束之后每一帧被调用,任何计算在Update里执行结束当LateUpdate开始时。LateUpdate常用为第三人称视角相机跟随。
7. OnDisable
当行为变为非启用(disable)或非激活(inactive)时调用。
3.8.6 Instantiate
Instantiate方法是用来实例化一个预制件的方法,支持泛型。
关键代码:
public GameObject perfab; public void AddGameObject(){ Instantiate (perfab); }
新建一个预制件,如图3-59所示。

图3-59
将预制件赋值给脚本,如图3-60所示。

图3-60
运行如下,每次点击都会生成一个新的游戏对象,如图3-61所示。

图3-61
3.8.7 Destory
Destory方法是用来删除一个游戏对象或者组件。当传入参数的类型是游戏对象时将删除该游戏对象;当传入参数的类型是其他组件的时候,将删除该组件。
关键代码:
public GameObject obj; public void ToDel(){ Destroy (obj); }
初始状态,如图3-62所示。

图3-62
点击按钮以后,如图3-63所示。

图3-63
3.8.8 获取指定游戏对象或组件
获取指定游戏对象或组件有5种方法。
(1)方法一,在窗口直接复制。
新建一个公开属性:
public cmptone one; Public cmptthree three;
然后在窗口将包含该组件的游戏对象托到变量里,可以是自身或者其他游戏对象,如图3-64所示。

图3-64
运行如图3-65所示。

图3-65
(2)方法二,如果组件在同一个游戏对象,可以用GetComponent方法获取制定组件,如图3-66所示。
GetComponent<cmpttwo> ().output();

图3-66
(3)方法三,可以用FindObjectOfType方法获取组件,无论对象是否和当前脚本在同一游戏对象,如图3-67所示。
FindObjectOfType<cmptfour>().output();

图3-67
(4)方法四,可以用GameObject.Find方法根据游戏对象名称获取指定名称的游戏对象,如图3-68所示。
GameObject.Find ("GameObject one").SetActive (false);

图3-68
(5)方法五,可以用GameObject.FindGameObjectWithTag方法根据游戏对象所在的Tag来获取游戏对象,如图3-69所示。
GameObject.FindGameObjectWithTag ("Player").SetActive (false);

图3-69
3.8.9 指定平台
Unity3D支持在代码里,可以让某段代码只在指定平台或Unity版本下运行。例如,下面代码将只在安卓平台下运行。
#if UNITY_ANDROID ..... #endif
3.8.10 DontDestroyOnLoad
用DontDestroyOnLoad可以将对象所在的游戏对象保留,当场景切换的时候不被销毁。
关键代码:
void Start () { DontDestroyOnLoad (gameObject); SceneManager.LoadScene ("showgo"); }
如图3-70所示,图中的方块就是从上一个场景中带过来的,这个方法也可以被用来在不同场景中传递数据信息。

图3-70
3.8.11 SendMessage
SendMessage方法可以用来调用制定游戏对象中的脚本组件的方法,无论该方法是否是公开方法。
脚本一(如图3-71所示):
void TestOne(){ Debug.Log ("this is one."); }

图3-71
脚本二(如图3-72所示):
void TestTwo(){ Debug.Log ("this is two"); }

图3-72
测试(如图3-73所示):
void Start () { SendMessage ("TestTwo"); GameObject.Find ("GameObject one").SendMessage ("TestOne"); }

图3-73
3.8.12 场景切换
场景切换过去是使用Application.LoadLevel方法,Unity 5.0以后,改用SceneManager.LoadScene方法。
切换的场景,必须都在“Scenes In Build”里,如图3-74所示。

图3-74
从场景“one”切换到场景“two”,如图3-75所示。

图3-75
代码如下:
SceneManager.LoadScene ("two");
或者
SceneManager.LoadScene (1);
这里的数字与“Scenes In Build”里一致。
点击之前,如图3-76所示。

图3-76
点击以后,如图3-77所示。

图3-77