下图是Unity 中各个类的继承关系:
- 每一个脚本默认都是继承MonoBehaviour的
- MonoBehaviour是继承Behaviour的
- Behaviour是继承Component的
- Component是继承Object的
- GameObject 是 继承Object的
点击这里进入Unity 官网文档了解更多。
- start 方法: 这个方法在游戏场景加载时被调用, 它只会执行一次。在该方法内可以写一些游戏场景初始化之类的代码.
- Update方法: 这个方法会在每一帧渲染之前被调用, 在每一帧都会执行很多次。大部分游戏代码在这里执行, 除了物理部分的代码。
- FixedUpdate方法: 这个方法会在固定的物理时间步调调用一次。这里也是基本物理行为代码执行的地方。
下图描述了Unity 中脚本的声明周期:
Reset() 只会在 Editor 模式下执行,当脚本首次附加在游戏对象时或者点击GameObject 的 Rest 按钮后会调用。Reset最常用于在检视面板中给定一个最常用的默认值.
- Editor 模式指的是编辑器使用的代码,当该游戏发布时,不会包含这些代码。如果属于编辑模式下的代码,需要放在 Editor 文件夹下,如果属于运行时执行的代码(比如说附加在游戏物体的脚本),应该放在任意的 非 Editor 文件夹下。 而且 Editor 文件夹的位置是很灵活的,可以作为其它目录的子目录,这样开发者就可以根据不同的功能来区分,将不同的功能的编辑代码放在不同的Editor 目录下。
- Awake() 是加载场景时运行,在脚本实例的整个生命周期中,Awake函数仅执行一次;Awake 方法总是运行在所有 Start 方法之前。
- 当一个GameObject 被实例化(或者创建)时会触发,但是如果游戏对象的初始状态为关闭状态,那么运行程序,Awake函数不会执行;如果游戏对象的初始状态为开启状态,那么Awake函数会执行。
- 值得注意的一点是,Awake函数的执行与否与脚本的状态(启用或禁用)并没有关系,而是与脚本所绑定的游戏对象的开关状态有关。如果重新加载场景,那么场景内Awake函数的执行情况重新遵循上述两点。
- Start()将在MonoBehavior创建后在该帧Update()第一次执行之前被调用;Start()函数只在脚本被 active 时才会执行;,但是对象上绑定的脚本被禁用了,那么Start函数不会执行。Start函数总是在Awake函数之后执行。
- 这是Start函数的特点,只有在脚本是 active 它才会执行,并且Start函数只会在脚本首次被active 时才会执行。如果是已经active 过的脚本被禁止后再次active,那么Start函数不会再次执行。
- OnDisable() 当一个对象 是 禁用的或者 非 active 时被触发 ,比如调用 GameObject.SetActive (false) 时
- OnGUI(): 绘制界面函数, 这个函数会每帧调用好几次(每个事件一次),GUI显示函数只能在OnGui中调用
- OnApplicationQuit() 应用程序退出时执行一次。
- OnLevelWasLoaded()用于通知游戏已加载新的场景
- OnApplicationPause() 当Play 游戏时点击中间暂停按钮的时候会调用。
- OnApplicationFocus,当程序获得或失去焦点时触发。
- 强制暂停时,先 OnApplicationPause,后 OnApplicationFocus;重新“启动”时,先OnApplicationFocus,后 OnApplicationPause;
一般开发中都是在Awake函数中获取游戏对象或者脚本实例的信息,然后在Start函数中进行一些获取之后的初始化设置。
- Awake、OnEnable、Start,都是游戏开始运行前就调用的方法。
- 如果 GameObject的Activity为true,脚本的enable为true时,其先后顺序为:Awake、OnEnable、Start;
- 如果 GameObject的Activity为true,脚本的enable为false时, 只运行Awake;
- 如果 GameObject的Activity为false时,以上都不调用,OnDisable()被调用;
那么必须使用 Awake 或 Start 方法 来初始化脚本的代码,两者的不同之处在于:
- Awake方法是在加载场景时运行;
- Start 方法是在第一次调用 Update 或 FixedUpdate 方法之前被调用;
- Awake 方法运行在所有 Start 方法之前。
- FixedUpdate, 该函数用于固定更新,在游戏运行的过程中,每一帧的处理时间是不固定的,当我们需要固定间隔时间来执行某些代码时,就会用到该函数。比如:游戏基本物理行为代码的地方。它是执行在Update之前。该函数在默认情况下 每0.02秒调用一次, 具体的时间间隔可以在TimeManager 中配置。 在 Editor -> Project Setting-> Time 中选择 Time Manager 即可配置。
- Update() 只能用在处于激活状态下的脚本,都会在每一帧调用一次 Update()函数 ,用于更新游戏场景和状态
- LateUpdate(),该函数属于延迟更新函数,处于激活状态下的脚本会在每一帧调用 在Update()后,每帧调用一次LateUpdate()。 通常用来调用代码的执行顺序。 比如玩家的角色需要一个摄像机来跟随, 那么通常角色的移动逻辑会写在Update()里。而摄像机跟随在Latelpdate()里, 这样可以确保在角色的位置计算完毕后, 再根据角色位置确定摄像机的位置和视角。
所以说 FixedUpdate() 会先调用,之后是Update(),最后是LateUpdate()
MonoBehaviour常用方法及调用顺序:
public class API01EventFunction : MonoBehaviour
{
private void Awake()
{
Debug.Log("Awake");
}
private void OnEnable()
{
Debug.Log("Enable");
}
private void Start()
{
Debug.Log("Start");
}
private void FixedUpdate()
{
Debug.Log("FixedUpdate");
}
private void Update()
{
Debug.Log("Update");
}
private void LateUpdate()
{
Debug.Log("LateUpdate");
}
private void OnApplicationPause(bool pause)
{
Debug.Log("OnApplicationPause");
}
private void OnDisable()
{
Debug.Log("OnDisable");
}
private void OnApplicationQuit()
{
Debug.Log("OnApplicationQuit");
}
private void Reset()
{
Debug.Log("Reset");
}
private void OnDestroy()
{
Debug.Log("OnDestroy");
}
}
点击这里了解官方的 GameObject 类详情。
public class API01EventFunction : MonoBehaviour
{
public GameObject prefab;
private void Start()
{
GameObject go = new GameObject("Plane"); //有时候为了组织 Hierarchy 的结构,可以动态创建空物体放置子对象
go.AddComponent(); // 给该物体添加一个组件
go.transform.position = new Vector3(0, 0, 0); // 重新设置物体的位置
// 该方法常用来实例化 Prefab 或者 克隆另一个游戏物体
GameObject gg = GameObject.Instantiate(prefab, prefab.transform.position, prefab.transform.rotation) as GameObject;
// 可以动态创建Unity 中内置的几何物体
GameObject gc = GameObject.CreatePrimitive(PrimitiveType.Plane);
gc.AddComponent();
gc.name = "Plane1"; // 设置物体的名字
gc.transform.Translate(new Vector3(0, 0, 0)); // 设置它的物体的位置
gc.GetComponent().enabled = false; // 禁用刚才添加的MeshCollider 组件
}
}
public class API01EventFunction : MonoBehaviour
{
public GameObject ob;
void Start()
{
// 通过GameObject或通过它的Component获取到的name都是GameObject的name
Debug.Log(ob.name);
Debug.Log(ob.GetComponent().name);
}
}
public static void Destroy(Object obj, float t = 0.0F);
- GameObject.Destroy : 删除一个游戏对象,组件或者资源 ( 调用后,游戏物体在场景中会立刻被删除,但是还没被回收;在Unity中会把将要销毁的游戏物体放入垃圾池统一管理)。
- 物体 obj 现在被销毁或在指定了t时间过后销毁。如果obj是一个Component,它将从GameObject中删除该组件并将其销毁。如果 obj 是GameObject它将销毁GameObject 以及其组件和全部 transform子物体。实际对象破坏始终延迟到当前Update循环之后,但始终在渲染之前完成。
public class API01EventFunction : MonoBehaviour
{
void DestroyGameObject()
{
Destroy(gameObject); // 销毁的是当前脚本所在的游戏物体
}
void DestroyScriptInstance()
{
// 删除当前物体上所在的脚本实例
Destroy(this);
}
void DestroyComponent()
{
// 删除的是当前脚本所在物体上的该组件
Destroy(GetComponent());
}
void DestroyObjectDelayed()
{
// 在5秒之后删除该脚本所在的游戏物体
Destroy(gameObject, 5);
}
// 当用户按下Ctrl键时,它将从游戏对象中销毁 BoxCollider 组件
void Update()
{// 当用户按下的是Ctrl键时 , 并且该物体上有 BoxCollider 组件,那么就销毁它
if (Input.GetButton("Fire1") && GetComponent())
{
Destroy(GetComponent());
}
}
}
点击 这里 进入官网。
public static void DontDestroyOnLoad(Object target);
- GameObject.DontDestroyOnLoad: 加载新场景时,请勿销毁目标对象。
- 默认情况下,重新加载一个新场景会销毁当前场景的所有对象。 调用 Object.DontDestroyOnLoad 可以在重新加载一个新场景加载期间保留原场景下该物体。 如果 参数 object target 是组件或GameObject,Unity还将保留该对象下的所有子对象。 Object.DontDestroyOnLoad 不返回值。 可以使用typeof运算符更改其参数类型。
public static Object FindObjectOfType(Type type);
- GameObject.FindObjectOfType: 根据 Type type 在场景中查找与其类型匹配的(返回找到的第一个)对象, 如果没有Object与 指定的类型匹配,则返回null。 注意,FindObjectOfType 将不会返回Assets(网格,纹理,预制件......)或 非active 对象。 它用于查找一个GameObject,但不会返回具有 HideFlags.DontSave设置的 Object。
- 请注意这个函数是非常慢的。不建议每帧都使用这个函数。在大多数情况下,您可以使用单例模式来代替。
public class API01EventFunction : MonoBehaviour
{
void Start()
{
Light light = FindObjectOfType< Light > ();
Debug.Log(light.name);
light.enabled = false;
Transform[] ts = FindObjectsOfType(); // 不会查找到未激活的对象
foreach(var tt in ts)
{
Debug.Log(tt.name);
}
}
}
GameObject.Find
public static GameObject Find(string name);
- 按名称查找 GameObject 并返回它。
- 此函数仅返回 active 的 GameObjects。 如果找不到带名称的GameObject,则返回null。 如果name包含'/'字符,它将像路径名一样遍历 hierarchy 面板。
- 出于性能原因,建议不要每帧都使用此方法。 而是在使用时将结果保存到成员变量中。 或者使用GameObject.FindWithTag。
- 注意:如果您希望查找子GameObject,通常使用 Transform.Find 更容易。
- 注意: 如果游戏运行多个场景,Find 将在所有场景中进行搜索。
public class NewBehaviourScript : MonoBehaviour
{
// 这将在其中一个场景中返回名为 Hand 的GameObject。
public GameObject Hand;
private void Start()
{
// 这将返回名为Hand的GameObject(游戏对象)
Hand = GameObject.Find("Hand");
// 返回名为Hand的GameObject(游戏对象)。Hand在Hierarchy视图中不能有父对象。
Hand = GameObject.Find("/Hand");
// 这将返回名为Hand的GameObject,它是Arm > Monster的子物体。 Monster在Hierarchy视图中不能有父对象。
Hand = GameObject.Find("/Monster/Arm/Hand");
// 这将返回名为Hand的GameObject,它是Arm > Monster的子对象。
Hand = GameObject.Find("Monster/Arm/Hand");
}
}
除了通过物体的 name 查找物体,通过物体的tag也可以查找。Tag即在Inspector上设置的一个标签,如下图所示:
一个物体只能有一个Tag,但是一个Tag可以被多个物体使用。
通过tag查找有两个方法:
GameObject.FindWithTag
public static GameObject FindWithTag(string tag);
返回第一个查找到的标签为 tag 的 active 为 true 的物体,如果没有找到则返回null。
tag 必须在TagManager中设置过 或 传递一个空字符串给该函数,否则会抛出异常。异常内容是:
UnityException: Tag: cat is not defined.
含义是:标签:xxx 没有定义
。GameObject. FindGameObjectsWithTag
public static GameObject[] FindGameObjectsWithTag(string tag);
- 由于一个Tag 可以被多个物体使用,所以这个方法可以找到所有使用该标签的 active 为 true 的物体,并返回对应的数组。如果没有找到,会返回一个空数组(长度为0的数组)。
- tag必须在TagManager中设置过 或 传递一个空字符串给该函数,否则会抛出异常。异常内容是:
UnityException: Tag: xxx is not defined.
含义是:标签:xxx 没有定义
。
public class ExampleClass : MonoBehaviour
{
public GameObject respawnPrefab;
public GameObject respawn;
void Start()
{
if (respawn == null)
respawn = GameObject.FindWithTag("Respawn");
Instantiate(respawnPrefab, respawn.transform.position, respawn.transform.rotation);
}
}
public class Test : MonoBehaviour
{
// Update is called once per frame
void Update()
{
GameObject name = GameObject.Find("Cube"); // 获取名称为 Cube 的游戏对象
name.transform.Translate(0, 0, 1); // 如果找到,就通过transform 对象的 Translate 变量 沿 z 轴 平移
name.GetComponent().doSomething(); // 找到该名字后,调用该物体上 NewBehaviourScript 脚本的 doSomething 函数
GameObject tag = GameObject.FindWithTag("someTag"); // 获取标签 为 "someTag" 的游戏对象
tag.transform.Translate(0, 0, 1);
tag.GetComponent().doSomething();
}
}
需要注意的是:这些方法的效率比较低,不要在Update中调用这些方法,否则可能会造成游戏卡顿。一般的做法是,在Awake或Start方法中通过Find找到,然后保存到成员变量中。
注意:
- 这个方法无法找到 active 为false的物体。
那么如何查找active为false的物体呢?
- 不要使用Find,可以直接在代码中通过 public 的变量在Inspector 上关联物体。
- 不要设置物体的active为false,可以在Start 函数中 通过代码找到物体,然后通过代码设为false
- 通过 使用 transform.Find
public void BroadcastMessage(string methodName, object parameter = null, SendMessageOptions options = SendMessageOptions.RequireReceiver);
- 在此游戏对象或其任何子对象(这些对象都是要 active 的)的每个脚本上(如果有的话)调用名为methodName的方法。
- 接收者的方法如果不需要第二个参数,可以 选择 null. 第三个参数当 options 被设置为SendMessageOptions.RequireReceiver时,如果接受者没有名为methodName的方法,否则程序报错。 如果不想打印错误, 可以设置为 MessageOptions. DontRequireReceiver。
public class API01EventFunction : MonoBehaviour
{
void Start()
{
/// Calls the function ApplyDamage with a value of 5
/// // Every script attached to the game object and all its children
// that has a ApplyDamage function will be called.
gameObject.BroadcastMessage("ApplyDamage", 5.0);
}
}
SendMessage
public void SendMessage(string methodName, object value = null, SendMessageOptions options = SendMessageOptions.RequireReceiver);
参数 methodName 为接受信息的方法名字;参数value为信息的内容,默认为null ; 参数options为信息接收的方式, 默认为SendMessageOptions.Require eceiver. 此方法的功能是调用该 Gameobject 其自身下每个脚本的名为methodName 函数, 对其作用范围说明如下。
- 和自身同级的物体不会收到消息, 例如, cube1和cube2的上一级父类都是cube0,则 cube2不会收到 cube1 发送的消息。
- SendMessageOptions 有两个可选方式: SendMessageOptions.RequireReceiver 和Send MessageOptions.DontRequireReceiver。前者要求信息的接收方必须有接受信息的方法, 否则程序会报错,后者则无此要求。
注意,消息不会发送到非激活的对象上(如,那些在编辑器或者通过SetActive已经关闭的对象)。
SendMessageUpwards
public void SendMessageUpwards(string methodName, object value = null, SendMessageOptions options = SendMessageOptions.RequireReceiver);
- 在此游戏对象或其父对象(这些对象都是要 active 的)的每个脚本上(如果有的话)调用名为methodName的方法。
- 接收者的方法如果不需要第二个参数,可以 选择 null. 第三个参数当 options 被设置为SendMessageOptions.RequireReceiver时,如果接受者没有名为methodName的方法,否则程序报错。 如果不想打印错误, 可以设置为 MessageOptions. DontRequireReceiver。
GetComponent 的第一个函数:
public Component GetComponent(Type type); // 其中参数type为组件的类型。
此方法用于获取 Gameobject 中第一个符合Type类型的Component。如果没有, 则返回null. 不会去子物体中去寻找。
public class ScriptExample : MonoBehaviour
{
void Start()
{
// Disable the spring on the HingeJoint component.
HingeJoint hinge = GetComponent();
hinge.useSpring = false;
}
}
GetComponent 的第二个函数(此方法不推荐使用):
public Component GetComponent(string type); //其中参数type为组件的名字。
此方法用于获取 Gameobject 中第一个符合Type 名字的Component。如果没有, 则返回null. 不会去子物体中去寻找。
public class ScriptExample : MonoBehaviour
{
void Start()
{
// Disable the spring on the HingeJoint component.
HingeJoint hinge = GetComponent("HingeJoint") as HingeJoint;
hinge.useSpring = false;
}
}
GetComponents :
public Component[] GetComponents(Type type);
有时一个游戏物体上可能有相同类型的组件,那么该操作的功能就是: 返回GameObject中所有Type类型的组件。 不会去子对象中需找,如果有的话。
public class Example : MonoBehaviour
{
void Start()
{
HingeJoint[] hinges = GetComponents();
for (int i = 0; i < hinges.Length; i++)
{
hinges[i].useSpring = false;
}
}
}
GetComponentInChildren:
public Component GetComponentInChildren(Type t);
功能是:用来获取当前 GameObject 或者所有子对象中符合Type类型的第一个组件。 注意:找到的 组件只有在active 的GameObject上找到时才会被返回。 说白了就是先在该物体自身身上查找,如果有,则返回。若没有,继续查找其子对象中第一个 Type 类型的组件。 否则,返回null
GetComponentsInChildren :
public Component[] GetComponentsInChildren(Type t, bool includeInactive);
GetComponentsInChildren(true);//游戏对象下的子物体激活的没激活的都会被获取,包括游戏对象本身
GetComponentsInChildren(false);//游戏对象下的子物体激活的会被获取, 包括游戏对象本身; 没激活的不会被获取
另外,()不写的活默认为false.
GetComponentInParent:
public Component GetComponentInParent(Type t);
返回 GameObject 或其任何(因为可能该对象的父对象可能也是一个子对象)父对象中第一个 Type类型 的组件。 注意: 该操作会向上递归,直到找到有效的组件。 如果未找到组件,则返回null。 仅返回active的 GameObject 上的组件。
GetComponentsInParent:
public Component[] GetComponentsInParent(Type t, bool includeInactive = false);
返回 GameObject 或其任何父对象中所有 Type 类型组件。
GetComponentsInParent(true); // 游戏对象的父对象激活的没激活的都会被获取该组件, 包括游戏对象本身
GetComponentsInParent(false); // 游戏对象的父对象激活的会被获取, 包括游戏对象本身; 没激活的不会被获取
另外,()不写的活默认为false.
public bool CompareTag(string tag);
该操作的功能是: 此游戏对象是否被标记为tag标签? 返回值为 bool
// Immediate death trigger.
// Destroys any colliders that enter the trigger, if they are tagged player.
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour
{
void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("Player"))
{
Destroy(other.gameObject);
}
}
}
public int GetInstanceID();
功能为: 返回物体的实例id。 注意的是: 物体的实例id 需要确保始终是唯一的。
public string ToString();
返回GameObject的名称。
点击 这里 进入 官方文档。
继承层次:
- Object->Component->Behaviour->MonoBehaviour
MonoBehaviour是所有脚本的基类,使用javascript的话,每个脚本都会自动继承自MonoBehaviour,但使用C#或Boo就必须显式从MonoBehaviour继承。
注意: 在 Unity Editor上有一个用于禁用 MonoBehaviour 的勾选框。 取消勾选时将禁用以下某些(如果脚本中有的话)函数。如果脚本中不存在这些函数,则编辑器不会显示勾选框。这些函数包括:
- Start()
- Update()
- FixedUpdate()
- LateUpdate()
- OnGUI()
- OnDisable()
- OnEnable()
public bool useGUILayout;
- 若为false,就可以跳过GUI布局阶段。仅仅在本次OnGUI调用中不使用GUI.Window和GUILayout时被使用。
- 它只用于在OnGUI中不使用GUI.Window和GUILayout的时候。
public void CancelInvoke();
- 在当前MonoBehaviour,取消所有 Invoke调用
public void CancelInvoke(string methodName);
- 在当前behaviour 上,取消所有方法名为 methodName的 Invoke调用。
public void Invoke(string methodName, float time);
- 在time时间内调用名字为 methodName 的函数
public void InvokeRepeating(string methodName, float time, float repeatRate);
- 在 time 时间内调用名字为 methodName的函数,然后每隔 repeatRate 秒重复调用一次该函数。
- Note : 如果你将第二个参数 time 设置为 0, 此操作将无效。
public bool IsInvoking(string methodName);
- 名字为 methodName 的函数是否在准备被等候调用
- 协同程序, 即在主程序运行时, 同时开启另一段逻辑处理, 来协同当前程序的执行。 换句话说, 开启一个协同程序就是开启另一个线程。
- 在Unity中, 使用 MonoBehaviour.StartCoroutine 方法即可开启一个协同程序, 也就是说, 该方法必须在MonoBehaviour或继承 MonoBehaviour的类中调用。 yield不可以在Update或者 FixedUpdate里使用
- 在Unity中, 使用 StartCoroutine(string methodName) 和 StartCoroutine(IEnumerator routine) 都可以开启一个协程。
- 在Unity中, 使用 StopCoroutine(string methodName) 来终止该 MonoBehaviour 指定方法名的一个协同程序,使用StopAllCoroutines() 来终止所有该MonoBehaviour可以终止的协同程序。
public Coroutine StartCoroutine(IEnumerator routine);
- 一个协同程序在执行过程中,可以在任意位置使用yield语句来暂停执行。yield return 时值决定了什么时候协程恢复执行。协程在协调在几帧中执行的操作时有极大的用处.,它几乎没有什么性能开销。StartCoroutine一般都会立即返回,然而你也可以获得返回结果的值。但是这一步会等到协程结束执行才能生效。不能保证协程结束的顺序与它们启动的顺序相同,即使它们在相同的帧中结束。
yield return null; //暂停协同程序,下一帧再继续往下执行
yield new WaitForFixedUpdate (); //暂停协同程序,等到下一次调用FixedUpdate方法时再继续往下执行
yield return new WaitForSeconds(2);//暂停协同程序,2秒之后再继续往下执行
yield return StartCoroutine("SomeCortoutineMethod");//暂停此协同程序,开启SomeCortoutineMethod协同程序,直到SomeCortoutineMethod协程执行完毕后,在继续执行当前协程。
public Coroutine StartCoroutine(string methodName, object value = null);
- 启动一个叫methodName方法的协同程序. 主要应用的场合是,当使用指定函数名字来开启协程时,就可以使用StopCoroutine来终止指定名字的函数。其缺点就是会有较高的性能开销,而且你只能传递一个额外的参数。
public void StopAllCoroutines();
终止运行在该MonoBehaviour上的所有协程。 通常一个脚本上可以运行多个 协程。注意:StopAllCoroutines 仅对其附加的一个脚本进行操作。
public void StopCoroutine(string methodName); public void StopCoroutine(IEnumerator routine); public void StopCoroutine(Coroutine routine);
methodName Name of coroutine. routine Name of the function in code, including coroutines. 停止第一个名为 methodName 的协程, 或者 存储 behaviour 中的名为 routine 正在运行的协程。
StopCoroutine接受三个参数中的一个,这些参数指定哪个coroutine被停止:
- - 第一个函数需要提供一个 名为 methodName 的(被 active)协程
- - 第二个函数需要提供一个 早已被创建的协程
- - 第三个函数需要提供一个 手动创建的 协程
如果在 StartCoroutine 中使用string 作为参数,请使用 StopCoroutine 中的提供的 string 。类似地,在StartCoroutine和StopCoroutine中都使用IEmonator。最后,将StopCoroutine与用于创建的Coroutine一起使用。
点击 这里 进入 官网。
在给定的秒数内,暂停协同程序的执行。
暂停的实际时间等于给定时间乘以Time.timeScale; 注:这里的时间会受到Time.timeScale的影响。 注意: WaitForSeconds只能与协程中的yield语句一起使用。
public class WaitForSecondsExample : MonoBehaviour
{
void Start()
{
StartCoroutine(Example());
}
IEnumerator Example()
{
print(Time.time);
yield return new WaitForSeconds(5);
print(Time.time);
}
}
在给定的秒数内,暂停协同程序的执行。
注:这里的时间不会受到Time.timeScale的影响。 注意: WaitForSecondsRealtime 只能与协程中的yield语句一起使用。
void Reset();
- 当脚本第一次被挂到object上或用户点击Inspector视图中Reset按钮时,Reset函数被调用来初始化脚本属性。Reset函数仅可以在编辑模式下被调用,常用于在Inspector视图中给定一个最常用的默认值.
void OnValidate();
- 当脚本被加载或Inspector中某个值被改变时,该函数被调用,仅能在编辑器状态下使用。用于确保在编辑器中修改数据时,该数据可以保持在特定范围内。
void OnLevelWasLoaded(int level)
- 该操作好像已在 Unity 5.4 就被抛弃了, 点击 这里 进入官网。
- 当一个新的level被加载之后调用该函数,可以做协程。可以在File->Build Settings中看到该level具体指的是哪个Scene。
- 可以 使用 SceneManager.sceneLoaded 来代替, 点击 这里 进入官网。
void Awake();
- 游戏启动之前用于初始化任何变量和游戏状态,在脚本实例生命周期中仅被调用一次,不能做协程。Awake函数是在所有objects实例化之后被调用的,所以你可以安全的与其他对象通信或用诸如使用 GameObject.FindWithTag 这样的函数搜索它们。同时,Awake函数是在任何Start函数之前被调用的,因而我们可以规定脚本的初始化顺序。每个 objects 之间Awake函数的调用没有先后顺序规定,因而可以利用Awake函数设置脚本之间的引用,再使用Start函数来回传递信息。
void Enable();
- 当场景开始运行时 ,对象被启用并且脚本为激活状态时此函数被调用。这通常发生于MonoBehaviour实例被创建时,不能做协程。
void Start();
- 如果脚本实例是enabled的,则 Start() 将在 MonoBehavior 创建后在该帧 Update() 第一次执行之前被调用,在脚本实例生命周期中仅被调用一次。不论脚本 Enabled 与否,Awake函数都会调用; 假如初始化期间脚本是 Disabled,则Start函数就不会与Awake函数在同一帧中被调用。
- Awake函数和OnEnable函数一定是在Start函数之前调用(好处是:object A实例化代码依赖于object B实例化,B的实例化就应该在Awake阶段完成,A的实例化就在Start阶段完成)。注意:对于添加到场景中的objects,所有脚本的Start函数都会在任何脚本调用Update等函数之前被调用。但是,在gameplay期间实例化objects,就不能强制遵循这个规则了。
void OnDisable();
- 当对象是禁用的或非激活状态时此函数被调用。当对象被销毁时,或对于任何清理工作的代码,该函数同样可被调用。当编译完成之后重新加载脚本,将调用 OnDisable ,脚本加载完成时调用OnEnable函数。该函数不可以做协程。
void OnDestroy();
- OnDestroy 发生在场景或游戏结束时 。当在场景运行时停止play 模式将结束应用程序,此时,OnDestroy将被执行。
- 此外,如果一个场景被关闭并加载了一个新场景,则会发出OnDestroy调用。
- 当构建为一个独立的应用程序时,OnDestroy 调用在场景结束时执行。场景结束通常意味着加载了一个新场景。
- 注意:只有先前状态为 active的对象,才会在 调用 OnDestroy 之后,才会被销毁。该函数不可以是协程。
void FixedUpdate();
- 假如MonoBehaviour是enabled时,该函数在固定帧率的每帧中被调用一次。比Update函数的调用更频繁;当帧率比较低时,每帧可被多次调用,如果帧率比较高,就可能不会被调用;所有的物理计算和更新都在FixedUpdate函数之后立即发生;当在FixedUpdate函数中计算物体移动时,不需要乘以Time.deltaTime,因为FixedUpdate函数是基于可靠的定时器,与帧率无关。
void Update();
- 假如MonoBehaviour是enabled时,该函数每帧被调用一次,是最主要最常用的帧更新函数。为了得到从上一帧调用Update函数到现在消耗的时间,需要使用Time.deltaTime。
void LateUpdate();
- 假如MonoBehaviour是enabled时,该函数每帧被调用一次,在Update函数之后执行;LateUpdate函数最常应用于第三人称的相机跟随。(如果将角色的移动和旋转放在Update函数中,则可以把相机的移动和旋转都放在LateUpdate函数,从而在相机追踪到角色位置之前,确保角色已经完成了移动。
- 注意:协程在所有Update函数完成后执行;若在LateUpdate中开启了一个协程,它将在LateUpdate之后渲染之前也会被调用。
void OnAnimatorIK(int layerIndex);
动画组件在更新它内部Inverse Kinematics(IK)系统之前调用该函数。可用于设置IK目标位置和他们各自的权重。
void OnAnimatorMove();
用于修改根运动而处理动画移动时调用。在状态机和动画计算完,OnAnimationIK之前,每帧都会被调用。
void OnAppllicationFocus(bool);
当玩家获得或失去焦点时,该消息被发送到所有游戏对象。该函数可以是协程,假如其作为协程来执行,在初始化帧期间会被用到两次:第一次用作前期消息通知,第二次发生在正常的协程更新步骤中。
void OnApplicationPause(bool);
当玩家暂停游戏,该消息会被发送给所有游戏对象。若暂停被检测到,当前帧执行后就调用OnApplicationPause函数,在正常的帧更新之间调用是有效的。在OnApplicationPause函数被调用后,增加额外的一帧来显示图像表明暂停状态。OnApplicationPause函数可以是协程,假如其作为协程来执行,在初始化帧期间会被用到两次:第一次用作前期消息通知,第二次发生在正常的协程更新步骤中。
void OnApplicationQuit();
在应用退出之前所有的游戏对象都会调用该函数。在编辑器中当用户停止播放时它将被调用;在webplayer中,当网页关闭时被调用。注意,IOS应用通常暂停并不会退出,所以应该在IOS播放器设置中勾选“Exit on Suspend”,这样会使游戏退出而不是暂停。如果没有勾选就会调用OnApplicationPause函数。
void OnBecameInvisible(); void OnBecameVisible();
当object在任何相机中变得可见/不可见时被调用,该消息被发送到任何挂在渲染器上的脚本。使用这两个函数可以避免不必要的计算,仅当object可见时才进行相应的计算。它们可以是协程。当在编辑器中运行时,场景视图摄像机也会导致它们被调用。
void OnCollisionEnter(Collision collision);
当该碰撞器/刚体开始接触到另一个刚体/碰撞器的时候,该函数被调用,可以做协程。和OnTriggerEnter函数相比,OnCollisionEnter的参数是Collision类而不是Collider。Collision类包含接触点,碰撞速度等信息,如果不需要在函数中使用这些碰撞信息,就不要考虑碰撞信息,这样可以避免不必要的计算。注意:碰撞事件仅仅当其中一个碰撞器中的也有一个non-kinematic刚体挂在时才会被发送。
void OnCollisionEnter2D(Collision2D collision);
当传进来的Collider和对象的Collider有接触时该函数被调用(仅限于2D物理)。
void OnCollisionExit(Collision collision);
当该碰撞器/刚体停止碰撞另一个刚体/碰撞器时被调用,可以做协程。和TriggerExit函数相比,OnCollisionExit 参数是Collision类而不是Collider。Collision类包含接触点,碰撞速度等信息,如果不需要在函数中使用这些碰撞信息,就不要考虑碰撞信息,这样可以避免不必要的计算。注意:碰撞事件仅仅当其中一个碰撞器中的也有一个non-kinematic刚体挂在时才会被发送。
void OnCollisionExit2D(Collision2D collision);
当传进来的Collider和对象的Collider停止接触时该函数被调用(仅限于2D物理)。
void OnCollisionStay(Collision collision);
对于每一个正在碰触其他刚体/碰撞器的碰撞器/刚体,该函数每帧都会被调用一次,可以做协程。和OnTriggerStay函数相比,OnCollisionStay参数是Collision类而不是Collider。Collision类包含接触点,碰撞速度等信息,如果不需要在函数中使用这些碰撞信息,就不要考虑碰撞信息,这样可以避免不必要的计算。注意:碰撞事件仅仅当其中一个碰撞器中的也有一个non-kinematic刚体挂在时才会被发送。
void OnCollisionExitStay2D(Collision2D collision);
当一个对象的Collider和这个对象的Collider正在碰撞时该函数被调用(仅限于2D物理)。
void OnControllerColliderHit(Controller ColliderHit);
当控制器执行时移动时碰到一个Collider上,该函数被调用。当它们碰撞到角色上时被用于推开对象。
void OnParticleCollision(GameObject);
当一个粒子撞到碰撞器上时该函数被调用。用于游戏对象受粒子碰撞时的伤害计算。
void OnConnectedToServer();
当成功连接到服务器时客户端调用该函数。
void OnDisconnectedFromServer(NetworkDisconnection);
当与服务器连接中断或终止连接时,该函数被调用。
void OnFailedToConnect();
由于某些原因尝试连接失败时,客户端调用该函数。
void OnFailedToConnectToMasterServer(NetworkConnectionError);
连接到主服务器有问题时服务器端或客户端调用该函数。
void OnMasterServerEvent(MasterServerEvent);
当收到来自主服务器报告事件,该函数被客户端或服务器端调用。
void OnServerInitialized();
不论何时Network.InitializeServer被触发并完成,服务器会调用该函数。
void OnSerializeNetworkView(BitStream, NetworkMessageInfo);
用于定制脚本中变量的同步,从网络的视角来看。自动决定是否序列化的变量应该被发送或接收。
void OnPlayerConnected(NetworkPlayer);
不论何时玩家成功连接到服务器时,服务器端调用该函数。
void OnPlayerDisconnected(NetworkPlayer);
不论何时玩家与服务器失去连接时,服务器端调用该函数。
void OnNetworkInstantiate(NetworkMessageInfo);
使用Network.Instantiate,对象被网络实例化时被调用。
void OnPreCull();
在相机剔除场景前被调用,剔除确定了哪些物体在相机中是可见的。仅当脚本挂在相机上并且是enabled时,该函数才会被调用。假如要修改相机的可视化参数(比如FOV,Transform等),就应该在这个函数中进行修改,此后场景中objects的可见性就取决于相机的参数了。
void OnWillRenderObject();
如果物体可见并且MonoBehaviour是enabled时,在渲染每个经过剔除操作之后的物体之前,它将为每个相机调用一次。
void OnPreRender();
仅当脚本挂在相机上并且是enabled时,则在相机开始渲染场景之前被调用。假如在这个函数中修改了相机的可视化参数(比如FOV),那么这些参数只会在下一帧中起到作用。该函数可以是协程。
void OnPostRender();
在相机完成场景的渲染后被调用。与OnRenderObject不同,仅当脚本挂在相机上并且是enabled时,该函数才会被调用。该函数可以做协程。假如想要在所有相机和GUI渲染之后做操作,使用WaitForEndOfFrame协程。
void OnRenderObject();
在所有固定场景渲染之后被调用,此时你可以使用GL类函数或者Graphics.DrawMeshNow来画自定义的几何体。该函数和OnPostRender函数相似,除了一点:不论脚本挂在相机上与否,OnRenderObject函数都会在任何挂有定义了该函数的脚本的object上被调用。
void OnRenderImage(RenderTexture, RenderTexture);
在场景渲染完成后被调用,用于对屏幕的图像进行后处理,该消息被发送到挂到相机上的所有脚本。该函数允许利用基于shader的过滤器对最终图像进行处理,传入源渲染纹理,终止于目标渲染纹理;当相机有多个图像过滤器时,按照图像顺序进行处理,前一个过滤器的目标渲染纹理作为下一个过滤器的源渲染纹理。
void OnGUI();
假如MonoBehaviour是disabled时,该函数不会被调用。为响应GUI事件,该函数每帧被调用多次,每个事件就调用一次;执行时先响应布局和重绘事件,随后是为每一次的输入事件执行布局和键盘/鼠标事件。
void OnDrawGizmos();
为了可视化的目的,在场景视图中绘制小图标。该函数使用相对于Scene视图的鼠标的位置,允许快速挑选场景中重要的objects,当然假如组件在inspector中collapsed,则该函数就不会被调用。
void OnDrawGizmosSelected();
同OnDrawGizmos,不过只有选中的物体执行。
void OnMouseEnter();
- 当鼠标移入到GUIElement(GUI元素)或Collider(碰撞体)中时调用OnMouseEnter。
- 如果对象属于 Ignore Raycast 层上,那么不能调用该函数
- 只有 当 Physics.queriesHitTriggers为真时,才会在标记为Trigger的碰撞器上调用此函数。
- OnMouseEnter可以作为一个协同程序,只需在函数中使用yield语句。 这个事件将发送到所有附在Collider或GUIElement的脚本上.
public class API01EventFunction : MonoBehaviour { public Renderer rend; void Start() { rend = GetComponent
(); } //当鼠标悬停在网格上时,网格变为红色, void OnMouseEnter() { rend.material.color = Color.red; } // 当鼠标移动时,红色渐渐变为青色, void OnMouseOver() { rend.material.color -= new Color(0.1F, 0, 0) * Time.deltaTime; } // 当鼠标移开时,网格最终变为白色。 void OnMouseExit() { rend.material.color = Color.white; } }
void OnMouseOver();
- 只要 当鼠标在 GUIElement 或 Collider上 停留时,每一帧中该函数都会被调用。
- 在鼠标悬停在对象上的第一帧上发生对OnMouseEnter的调用。 然后每帧调用OnMouseOver,直到鼠标离开,此时调用OnMouseExit。
- 如果对象属于 Ignore Raycast 层上,那么不能调用该函数
- 只有 当 Physics.queriesHitTriggers为真时,才会在标记为Trigger的碰撞器上调用此函数。
- OnMouseOver 可以是一个协程,只需在函数中使用yield语句。该事件将发送到所有附在Collider或GUIElement的脚本上。
void OnMouseExit();
- 当鼠标从 GUIElement 或 Collider 离开时该函数被调用。
- 对 OnMouseExit的 调用可以跟在对 OnMouseEnter 和 OnMouseOver 的相应调用之后。
- 如果对象属于 Ignore Raycast 层上,那么不能调用该函数
- 只有 当 Physics.queriesHitTriggers为真时,才会在标记为Trigger的碰撞器上调用此函数。
- 如果在该函数中的某处添加yield语句,则可以使用OnMouseExit作为协程。此事件将发送到所有附在Collider或GUIElement的脚本上。
public class API01EventFunction : MonoBehaviour { // 将此脚本附加到 GameObject 上,以便在鼠标悬停在其上时输出消息。 void OnMouseOver() { //如果您的鼠标悬停在带有脚本的GameObject上,则输出此消息 Debug.Log("Mouse is over GameObject."); } void OnMouseExit() { //鼠标不再悬停在GameObject上,因此每帧输出此消息 Debug.Log("Mouse is no longer on GameObject."); } }
void OnMouseDown();
- 当用户在GUIElement或Collider上按下鼠标时该函数被调用,该事件消息会被发送给Collider或GUIElement的所有脚本。
- 如果对象属于 Ignore Raycast 层上,那么不能调用该函数
- 只有 当 Physics.queriesHitTriggers为真时,才会在标记为Trigger的碰撞器上调用此函数。
- OnMouseDown 可以是一个协程
using UnityEngine; using System.Collections; using UnityEngine.SceneManagement; public class ExampleClass : MonoBehaviour { void OnMouseDown() { // load a new scene SceneManager.LoadScene("OtherSceneName"); } }
void OnMouseUp();
- 当用户释放鼠标按键时,该函数被调用。只会执行一次
- 请注意,即使鼠标已经不在和鼠标按下相同的一个GUIElement或Collider上时,也会调用OnMouseUp。有关类似按钮的行为,请参见: OnMouseUpAsButton。
- 如果对象属于 Ignore Raycast 层上,那么不能调用该函数
- 只有 当 Physics.queriesHitTriggers为真时,才会在标记为Trigger的碰撞器上调用此函数。
- 如果在该函数中的某处添加yield语句,则可以使用 OnMouseUp 作为协程。此事件将发送到所有附在Collider或GUIElement的脚本上。
void OnMouseUpAsButton();
- OnMouseUpAsButton只有当鼠标在同一个GUIElement或Collider按下时,在释放鼠标按键时,该函数被调用。
- 如果对象属于 Ignore Raycast 层上,那么不能调用该函数
- 只有 当 Physics.queriesHitTriggers为真时,才会在标记为Trigger的碰撞器上调用此函数。
- 如果在该函数中的某处添加yield语句,则可以使用 OnMouseUpAsButton 作为协程。此事件将发送到所有附在Collider或GUIElement的脚本上。
void OnMouseDrag();
- 当用户鼠标在GUIElement或Collider上拖拽时,OnMouseDrag被调用 。当鼠标按下时,每一帧都会调用OnMouseDrag。
- 如果对象属于 Ignore Raycast 层上,那么不能调用该函数
- 只有 当 Physics.queriesHitTriggers为真时,才会在标记为Trigger的碰撞器上调用此函数。
- 如果在该函数中的某处添加 yield 语句,则可以使用 OnMouseDrag作为协程。此事件将发送到所有附在Collider或GUIElement的脚本上。
void OnTriggerEnter(Collider);
- 当碰撞体进入触发体时,该函数被调用。该消息会被发送给触发器和碰撞该触发器的碰撞器。
- 两个GameObject中的任何一个都必须具有Rigidbody组件。 Rigidbody 组件将 Rigidbody.useGravity 和Rigidbody.isKinematic 都设置为false。 这样可以防止GameObject在重力作用下坠落并具有运动行为。
- 一个 Collider 需要将 Collider.isTrigger 设置为true。 将 Collider.isTrigger 设置为 true 的GameObject与其它GameObject 碰撞或穿过时,将调用OnTriggerEnter。通常, 在 FixedUpdate结束后发生OnTriggerEnter。
void OnTriggerEnter2D(Collider2D);
当另一个对象碰到这个对象上挂有的触发器碰撞器时,该消息被发送(仅仅2D物理适用)。
void OnTriggerExit(Collider);
- 当Collider(碰撞体)停止触发trigger(触发器)时调用OnTriggerExit。该消息被发送给触发器和碰撞触发器的碰撞器。
- 注意,只有在其中一个碰撞器也有刚体挂载时,触发事件才会被发送。
- OnTriggerExit 可以是一个协程,只需在函数中使用yield语句即可。
void OnTriggerExit2D(Collider2D);
当另一个对象离开这个对象上挂有的触发器碰撞器时,该消息被发送(仅仅2D物理适用)。
void OnTriggerStay(Collider);
- 当每个碰撞体接触触发器时,OnTriggerStay将在每一帧被调用。该消息会被发送给触发器和碰撞该触发器的碰撞器,注意,只有在其中一个碰撞器也有刚体挂载时,触发事件才会被发送。
- OnTriggerStay可以是一个协程,只需在函数中使用yield语句即可。
void OnTriggerStay2D(Collider2D);
当另一个对象在该对象的触发器碰撞器内时该函数每帧被都会被调用。(仅仅2D物理适用)
void OnJointBreak(float);
当连接到同一游戏对象上的关节断裂时被调用。当外力高于关节的breakForce时,关节会断开。当关节断开时,该函数被调用,施加于关节处的断裂外力会被做为参数传入。当该函数完成后,关节会自动从游戏对象上移除。