unity3d学习(十四)代码的生命周期相关方法



(一)常见的生命周期方法

在 Unity 中,除了 Awake() 之外,还有其他许多常用的生命周期函数,它们在游戏对象或脚本组件的生命周期中的不同阶段被调用,

允许开发者在适当的时候执行特定的代码。以下是一些常用的 Unity 生命周期函数:


(1)Start()

调用时机:在 Awake() 之后调用,仅当脚本实例首次被启用时调用一次。

用途:通常用于进行一些初始化操作,如设置初始状态、加载资源等。

(2)Update()

调用时机:在每一帧渲染之前调用。

用途:用于更新游戏对象的逻辑,如处理输入、移动、碰撞检测等。由于它是在每一帧都调用,

因此适合处理需要频繁更新的逻辑。


(3)FixedUpdate()

调用时机:在固定的时间间隔内调用,通常用于处理物理模拟。

用途:由于不同设备的性能不同,Update() 函数的执行频率可能会有所不同,

而 FixedUpdate() 则是在固定的时间间隔内执行,保证物理模拟的稳定性。

(4)LateUpdate()

调用时机:在所有 Update() 函数执行完毕后调用。

用途:通常用于处理需要在所有其他更新之后发生的操作,如摄像机跟随、物体的追踪等。

(5)OnEnable()

调用时机:当游戏对象或脚本组件被激活时调用。

用途:用于处理对象的启用逻辑,如订阅事件、注册回调等。当

对象从非激活状态变为激活状态时,这个函数会被调用。

(6)OnDisable()

调用时机:当游戏对象或脚本组件被禁用时调用。

用途:用于处理对象的禁用逻辑,如取消订阅事件、注销回调等。

当对象从激活状态变为非激活状态时,这个函数会被调用。

(7)OnDestroy()

调用时机:当游戏对象或脚本组件被销毁时调用。

用途:用于处理对象的销毁逻辑,如资源释放、清理操作等。

在对象被销毁之前,这个函数会被调用。


(8)此外,Unity 还提供了一些特定场景下使用的生命周期函数,如:


OnCollisionEnter():当带有 Collider 或 Rigidbody 组件的物体触碰另外一个带有 

  Collider 或 Rigidbody 组件的物体时,在开始碰撞时调用。

OnCollisionStay():当带有 Collider 或 Rigidbody 组件的物体持续触碰另外一个带有

   Collider 或 Rigidbody 组件的物体时,每帧都会被调用。

OnCollisionExit():当带有 Collider 或 Rigidbody 组件的物体停止触碰另外一个带有 

  Collider 或 Rigidbody 组件的物体时,在停止碰撞时调用。

OnTriggerEnter():当 Collider 进入 Trigger 时调用。

OnTriggerStay():当 Collider 持续接触 Trigger 时,每帧都调用。

OnTriggerExit():当 Collider 停止触发 Trigger 时调用。

这些函数允许开发者在碰撞和触发器事件发生时执行特定的代码。


(9)Awake() 

Awake() 是 Unity 引擎中一个非常重要的生命周期方法,它属于 MonoBehaviour 类。

在 Unity 中,MonoBehaviour 是所有脚本的基类,提供了许多用于游戏对象行为定义的方法。

Awake() 方法就是在游戏对象被实例化并首次激活时自动调用的一个方法。


以下是 Awake() 方法的一些关键特点:


自动调用:当游戏对象被加载到场景中,并且该对象上的脚本被实例化时,Awake() 方法会自动被调用一次。

这意味着,无论游戏对象是通过脚本动态创建的,还是在编辑器中预先放置的,

只要它进入活动状态,Awake() 就会执行。


执行顺序:在 Unity 的生命周期中,Awake() 方法通常在 OnEnable() 之前被调用,

但可能在 Start() 之前或之后,

这取决于脚本的执行顺序和依赖关系。然而,如果两个脚本都在同一个游戏对象上,

并且都定义了 Awake() 和 Start() 方法,那么它们的 Awake() 方法会先按照脚本在编辑器中的顺序执行,

然后是 Start() 方法。


初始化:Awake() 方法通常用于初始化脚本变量、设置游戏对象的初始状态或执行其他一次性设置任务。

它是确保游戏对象在首次激活时处于正确状态的好地方。


线程安全:与构造函数或字段初始化器不同,Awake() 方法是在 Unity 的主线程上执行的。

这意味着你可以安全地在 Awake() 中调用 Unity 的 API,如 transform、renderer 等,

而无需担心线程安全问题。


依赖注入:在某些情况下,Awake() 方法也用于实现依赖注入模式,

即一个游戏对象通过查找其他游戏对象上的组件来建立依赖关系。

这通常通过 GameObject.Find()、Transform.Find() 或 GetComponent<T>() 等方法实现。


单例模式:Awake() 方法也常用于实现单例模式,确保一个类只有一个实例,并提供一个全局访问点。

在这种情况下,Awake() 方法会检查是否已经存在一个实例,如果不存在,则创建并返回它;

如果存在,则直接返回现有实例。


注意事项:虽然 Awake() 方法非常有用,但你应该注意不要在它里面执行耗时的操作,

因为这可能会导致游戏在加载时卡顿。

此外,如果多个脚本都依赖于彼此的初始化,你可能需要小心处理它们的执行顺序和依赖关系。




(二)一个常见的错误:get_transform 方法只能在主线程中被调用

这是一个常见的错误,不光是get_transform,实际上所有的unity api都不可以在非主线程进行调用。

会报下面的错误:

get_transform can only be called from the main thread.

Constructors and field initializers will be executed from the loading thread when loading a scene.

Don't use this function in the constructor or field initializers,

 instead move initialization code to the Awake or Start function.


get_transform 方法只能在主线程中被调用。在Unity中,当加载场景时,

构造函数和字段初始化器会在加载线程中执行,而不是主线程。

因此,在构造函数或字段初始化器中使用依赖于主线程的Unity API(如get_transform)会导致问题。



另外的解决方法是借助于第三方类UnityMainThreadDispatcher。

源码地址:

https://gitcode.com/gh_mirrors/un/UnityMainThreadDispatcher/overview?utm_source=artical_gitcode&index=top&type=card&webUrl


这个类使用的时候,你把它附加到场景上任何一个对象,例如主相机。

然后像下面这样使用即中。

Usage

	public IEnumerator ThisWillBeExecutedOnTheMainThread() {
		Debug.Log ("This is executed from the main thread");		yield return null;
	}	public void ExampleMainThreadCall() {
		UnityMainThreadDispatcher.Instance().Enqueue(ThisWillBeExecutedOnTheMainThread()); 
	}

OR

	UnityMainThreadDispatcher.Instance().Enqueue(() => Debug.Log ("This is executed from the main thread"));

有了它,就可以直接在非主线程调用unity api,非常方便。


下面这篇文章还讲到了使用这种类进行单例的应用(它说的类和UnityMainThreadDispatcher类似):

https://blog.csdn.net/weixin_47420447/article/details/137219543



本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:
本帖最后由 勇哥,很想停止 于 2024-10-29 09:01:26 编辑

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2025年4月    »
123456
78910111213
14151617181920
21222324252627
282930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864