[注解]Execution Order of Event Functions: Unity生命周期及常见问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jingangxin666/article/details/82961358

版本: 2018.2

原文: Execution Order of Event Functions

Script Lifecycle Flowchart 脚本生命周期流程图

The following diagram summarises the ordering and repetition of event functions during a script’s lifetime.

img

In Unity scripting, there are a number of event functions that get executed in a predetermined order as a script executes. This execution order is described below:

Unity框架有一个复杂的游戏循环

First Scene Load 第一次场景加载

These functions get called when a scene starts (once for each object in the scene).

  • Awake:

    • This function is always called before any Start functions and also just after a prefab is instantiated. (If a GameObject is inactive during start up Awake is not called until it is made active.)
    • 调用时机:
      • 在prefab被实例化之后调用(todo)
      • 在调用 Start 之前调用
    • 注意:
      • 如果GameObject在游戏启动时处于非活动状态,则不会调用 Awake , 直到它被激活才会调用 Awake
      • 不切换场景的情况下, Awake 只会在首次激活时调用, (只调用一次)
      • 在所有对象都初始化之后, 才调用 Awake , 所以可以安全地与其他对象交互, 或使用例如 GameObject.FindWithTag 来查找对象
      • 在Unity中, 使用 Awake 而不是构造函数来进行初始化,因为组件的序列化状态在构造时未定义。 Awake 仅被调用一次,就像构造函数一样。
      • Awake 不能作为协程
      • 任何 Start 调用之前, 总是先调用 Awake
  • OnEnable:

    • (only called if the Object is active): This function is called just after the object is enabled. This happens when a MonoBehaviour instance is created, such as when a level is loaded or a GameObject with the script component is instantiated.
    • 调用时机
      • MonoBehaviour实例被创建之后(例如关卡加载时, 或GameObject的脚本被实例化)
      • 对象启用后立即调用此函数
    • 注意:
      • 仅在Object处于激活状态时调用 (激活对象的函数有: GameObject.SetActive(true))
      • 每次启动时都会调用!(启动对象的函数有 object.enable = true )
  • OnLevelWasLoaded:

    • This function is executed to inform the game that a new level has been loaded.
    • 调用时机:
      • 当一个新的关卡被加载完毕的时候
    • 类似功能的API

Note that for objects added to the scene, the Awake and OnEnable functions for all scripts will be called before Start, Update, etc are called for any of them. Naturally, this cannot be enforced when an object is instantiated during gameplay.

扫描二维码关注公众号,回复: 3472426 查看本文章

Editor 编辑器

  • Reset:
    • Reset is called to initialize the script’s properties when it is first attached to the object and also when the Reset command is used.
    • 执行时机:
      • 当脚本第一次被附着到GameObject上面时, 该MonoBehavior的属性会进行初始化
      • 或者执行 Reset 命令时, (编辑器脚本中或者在编辑器界面鼠标右键选择"Reset")
    • 注意:
      • 在编辑器环境下起作用

Before the first frame update 第一帧更新之前

  • Start:
    • Start is called before the first frame update only if the script instance is enabled.
    • 调用时机:
      • 在第一帧更新之前调用
      • 只有在脚本被激活时它才会执
    • 注意:
      • 第一帧更新之前调用, 说明理论上只会调用一次!!
      • 如果GameObject被激活时, 该脚本对象没有被启动, 则该Start 不会被调用
      • 如果偏要多调用几次 Start , 可以在代码里面写 Start();

For objects added to the scene, the Start function will be called on all scripts before Update, etc are called for any of them. Naturally, this cannot be enforced when an object is instantiated during gameplay.

In between frames 在帧之间

  • OnApplicationPause:
    • This is called at the end of the frame where the pause is detected, effectively between the normal frame updates. One extra frame will be issued after OnApplicationPause is called to allow the game to show graphics that indicate the paused state.
    • 调用时机:
      • 当检测到暂停时, 有效的正常帧更新之间, 调用此函数
    • 注意:
      • 调用此函数后, 有额外的一帧被允许来处理图像显示(比如显示游戏处于暂停状态)

Update Order 更新顺序

When you’re keeping track of game logic and interactions, animations, camera positions, etc., there are a few different events you can use. The common pattern is to perform most tasks inside the Update function, but there are also other functions you can use.

在处理有关游戏逻辑, 状态, 动画, 相机位置的时候, 有好几个关于更新的函数可以使用

  • FixedUpdate:
    • FixedUpdate is often called more frequently than Update. It can be called multiple times per frame, if the frame rate is low and it may not be called between frames at all if the frame rate is high. All physics calculations and updates occur immediately after FixedUpdate. When applying movement calculations inside FixedUpdate, you do not need to multiply your values by Time.deltaTime. This is because FixedUpdate is called on a reliable timer, independent of the frame rate.
    • 调用时机:
      • 基于可靠的定时器调用,与帧率无关
    • 注意:
      • 当帧率低的时候, 可能会一帧调用多次
      • 当帧率高的时候, 可能不会每一帧都调用
      • FixedUpdate的时间间隔可以在项目设置中更改,Edit->ProjectSetting->time 找到Fixedtimestep
      • 不要滥用 FixedUpdate 方法,因为它是用来处理物理模拟的,更重要的是它并非根据真实时间的间隔执行
    • 使用场景:
      • 处理物理模拟: 当向刚体添加力时,必须在FixedUpdate内的每个固定帧上应用力,而不是在Update中的每个帧
    • 更多:
  • Update:
    • Update is called once per frame. It is the main workhorse function for frame updates.
    • 调用时机:
      • 每一帧, 这是帧更新最主要的方法
    • 注意:
      • 这个函数的更新频率和设备的性能有关以及被渲染的物体(可以认为是三角形的数量)
      • 为了获得自上次调用Update以来经过的时间, 可以使用Time.deltaTime.
    • 更多:
  • LateUpdate:
    • LateUpdate is called once per frame, after Update has finished. Any calculations that are performed in Update will have completed when LateUpdate begins. A common use for LateUpdate would be a following third-person camera. If you make your character move and turn inside Update, you can perform all camera movement and rotation calculations in LateUpdate. This will ensure that the character has moved completely before the camera tracks its position.
    • 调用时机:
      • 每一帧都调用
      • Update 函数执行完毕之后调用
    • 使用场景:

Rendering 渲染

  • OnPreCull:
    • Called before the camera culls the scene. Culling determines which objects are visible to the camera. OnPreCull is called just before culling takes place.
    • 在相机场景剔除前调用
  • OnBecameVisible/OnBecameInvisible:
    • Called when an object becomes visible/invisible to any camera.
    • 当一个物体对任意摄像机变得可见/不可见时被调用
  • OnWillRenderObject:
    • Called once for each camera if the object is visible.
    • 当物体被相机渲染之前调用
  • OnPreRender:
    • Called before the camera starts rendering the scene.
    • 在相机开始渲染场景之前调用
  • OnRenderObject:
    • Called after all regular scene rendering is done. You can use GL class or Graphics.DrawMeshNow to draw custom geometry at this point.
    • 在所有特定的场景渲染完成之后调用
    • 可以使用GL类或者Graphics.DrawMeshNow 来绘制自定义几何体
  • OnPostRender:
    • Called after a camera finishes rendering the scene.
    • 当相机完成场景的渲染工作后调用
    • 可以用来指定区域截图, 查看Texture2D.ReadPixels
  • OnRenderImage:
    • Called after scene rendering is complete to allow post-processing of the image, see Post-processing Effects.
    • 当场景的渲染工作完成之后, 可以用来进行图像的后处理
  • OnGUI:
    • Called multiple times per frame in response to GUI events. The Layout and Repaint events are processed first, followed by a Layout and keyboard/mouse event for each input event.
    • 调用时机:
      • 一帧调用多次(为了响应GUI事件)
    • 注意:
      • 先处理布局和重绘事件
      • 再处理布局和每个输入事件
      • 可以用来编辑器工具的绘制
  • OnDrawGizmos
    • Used for drawing Gizmos in the scene view for visualisation purposes.
    • 可以用来在Scene视图内绘制小玩意
    • 例如射线, 正方体, 球体, 相机的视锥体等(可以用在动态地图可视化调试的辅助工具?)

Coroutines 协同程序

Normal coroutine updates are run after the Update function returns. A coroutine is a function that can suspend its execution (yield) until the given YieldInstruction finishes. Different uses of Coroutines:

正常的协同程序更新是在Update函数返回之后运行

  • yield
    • The coroutine will continue after all Update functions have been called on the next frame.
    • 调用时机:
      • 下一帧中, 且所有Update函数调用完毕之后
  • yield WaitForSeconds
    • Continue after a specified time delay, after all Update functions have been called for the frame
    • 调用时机:
      • 在指定时间延迟之后的那一帧, 且所有Update函数调用完毕之后之后调用
  • yield WaitForFixedUpdate
    • Continue after all FixedUpdate has been called on all scripts
    • 等待所有的 FixedUpdate 函数调用完毕之后
  • yield WWW
    • Continue after a WWW download has completed.
    • 等待WWW下载完毕之后执行
  • yield StartCoroutine
    • Chains the coroutine, and will wait for the MyFunc coroutine to complete first.
    • 等待 MyFunc 协程执行完毕之后

When the Object is Destroyed 对象被销毁的时候

  • OnDestroy:
    • This function is called after all frame updates for the last frame of the object’'s existence (the object might be destroyed in response to Object.Destroy or at the closure of a scene).
    • 调用时机:
      • object生命周期的最后一帧中, 所有帧更新完毕之后调用
      • 调用 Object.Destroy 函数之后
      • 切换场景或结束游戏的时候

When Quitting 退出游戏

These functions get called on all the active objects in your scene:

  • OnApplicationQuit:
    • This function is called on all game objects before the application is quit. In the editor it is called when the user stops playmode.
    • 调用时机:
      • 游戏结束之前
      • 编辑器模式下, 停止游戏运行的时候
  • OnDisable:
    • This function is called when the behaviour becomes disabled or inactive.
    • 当MonoBehavior被禁用(SetActive(false) 或 Object.Enable(false))的时候调用(与 OnEnable 相反)

常见问题:

Awake和Start的区别是什么?

两者的关系?

  • Awake和Start函数在脚本生命周期中都是只调用一次

  • 在脚本对象初始化完成后, 无论它是否启动(但是它得处于激活状态), 都会调用Awake; 而Start仅会在启动的时候才会在同一帧被调用

  • Awake在Start之前调用

两者如何配合?

  • 如果A对象的初始化工作需要依赖到B对象初始化完毕的资源, 则B的初始化工作需要在Awake内进行, A的初始化工作需要在Start内进行

  • 每个GameObject的不同脚本对象的Awake是随机顺序调用的, 应该使用Awake来设置脚本间的相互引用,并使用Start来回传递任何信息。

对象激活和对象启用的区别?

我个人的理解是这样(暂时找不到资料呀…):

一个GameObject可以有很多个脚本对象objects, 那么激活GameObject对象可以在Inspector面板勾选, 也可以使用GameObject.SetActive(true)函数, 启动脚本对象可以在Inspector面板勾选, 也可以使用object.enable = true函数

img

猜你喜欢

转载自blog.csdn.net/jingangxin666/article/details/82961358