单例脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 using System.Collections;using System.Collections.Generic;using UnityEngine;public class SingleScript : MonoBehaviour { public static SingleScript instance; static SingleScript ( ) { GameObject go = new GameObject("#Global#" ); DontDestroyOnLoad(go); instance = go.AddComponent<SingleScript>(); Debug.Log("static construct function has finished" ); } void Start ( ) { Debug.Log("Global script start" ); } void Awake ( ) { Debug.Log("Global script Awake" ); } public void Dosomething ( ) { Debug.Log("Global script do something" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 using System.Collections;using System.Collections.Generic;using UnityEngine;public class SingleTestMain : MonoBehaviour { private void OnGUI ( ) { if (GUILayout.Button("执行单例脚本中的方法" )) { SingleScript.instance.Dosomething(); } } }
运行过程及说明: SingleTestMain.cs 需要挂载在物体身上,因为要用它来模拟调用 Global 脚本中的方法。SingleScript.cs 不需要在编辑器模式下就挂载在物体身上,但是依然需要继承自 Monobehaviour,因为在点击 “执行单例脚本中的方法” 的 Button 时,会在场景中创建一个 “#Global#” 的 GameObject,并添加一个 SingleScript 的组件,并将 instance 指向该组件。输出如下:
Global script Awake
static construct function has finished
Global script do something
Global script start
可以看到,在没有点 Button 之前是没有任何输出的,并且官网上也提到 静态构造函数 的调用时机不受我们控制。暂时只需要记住静态构造函数用于初始化任何静态数据,或执行仅需执行一次的特定操作。 将在创建第一个实例或引用任何静态成员之前自动调用静态构造函数。 还需要注意一下 4 个函数的执行顺序,Awake 是在 go.AddComponent<SingleScript>()
时执行的,然后静态构造函数执行完,再执行成员方法,最后才是 Start 方法。
定时器 UnityAction public delegate void UnityAction();
类似于 c# 中的 Action
,是一个没有返回值,没有参数的委托。
协程 注意:禁用 MonoBehaviour 时,不会停止协程,仅在明确销毁 MonoBehaviour 时才会停止协程。可以使用 MonoBehaviour.StopCoroutine 和 MonoBehaviour.StopAllCoroutines 来停止协程。销毁 MonoBehaviour 时,也会停止协程。
定时器实现 定时器可以使用协程来完成,但是这样就必须依赖于脚本,但是我们可以使用一个继承自 MonoBehaviour 的空的内部类来封装一个不依赖于脚本的定时器。 代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.Events; public class Script_04_18 { private static TaskBehaviour m_task; static Script_04_18 ( ) { GameObject go = new GameObject("#WaitTimeManager#" ); GameObject.DontDestroyOnLoad(go); TaskBehaviour t = go.AddComponent<TaskBehaviour>(); m_task = t; } public static Coroutine WaitTime (float time,UnityAction callback ) { return m_task.StartCoroutine(Coroutine(time, callback)); } public static void StopCoroutine (ref Coroutine coroutine ) { if (coroutine != null ) { m_task.StopCoroutine(coroutine); coroutine = null ; } } private static IEnumerator Coroutine (float time,UnityAction callback ) { yield return new WaitForSeconds (time ) ; if (callback != null ) { callback(); } } class TaskBehaviour :MonoBehaviour {} }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.Events;public class Script_04_18_main : MonoBehaviour { private Coroutine coroutine; private void OnGUI ( ) { if (GUILayout.Button("开启定时任务" )) { Debug.Log("10 秒之后打印一段 Rap" ); coroutine = Script_04_18.WaitTime(10 , PrintRap); } if (GUILayout.Button("停止定时任务" )) { Script_04_18.StopCoroutine(ref coroutine); } } static void PrintRap ( ) { Debug.Log("一段 Rap" ); } }
运行效果: 在点击了 “开启定时任务” 十秒之后,会打印出
如果在十秒之前,点击了 “停止定时任务”,那么不会有 “一段 Rap” 的输出