Unity3D_02_基类MonoBehaviour/自带函数以及脚本执行的生命周期
导引:
其中Time,Input,Physics都是Unity中的全局变量。GameObject是游戏中的基本物件。GameObject是由Component组合而成的,GameObject本身必须有Transform的Component,这也加深了我们对GameObject的理解,即GameObject是游戏场景中真实存在,而且有位置的一个物件。
但是我们怎么操纵这个GameObject呢?这就需要引入脚本组件了,也就是所有脚本组件的基类MonoBehaviour。
MonoBehaviour的生命周期:
MonoBehaviour是Unity中所有脚本的基类,如果你使用JS的话,脚本会自动继承MonoBehaviour。如果使用C#的话,你需要显式继承MonoBehaviour。
在我们使用MonoBehaviour的时候,尤其需要注意的是它有哪些可重写函数,这些可重写函数会在游戏中发生某些事件的时候被调用。我们在Unity中最常用到的几个可重写函数是这几个:
Awake:当一个脚本实例被载入时Awake被调用。我们大多在这个类中完成成员变量的初始化
Start:仅在Update函数第一次被调用前调用。因为它是在Awake之后被调用的,我们可以把一些需要依赖Awake的变量放在Start里面初始化。 同时我们还大多在这个类中执行StartCoroutine进行一些协程的触发。要注意在用C#写脚本时,必须使用StartCoroutine开始一个协程,但是如果使用的是JavaScript,则不需要这么做。
Update:当MonoBehaviour启用时,其Update在每一帧被调用。
FixedUpdate:当MonoBehaviour启用时,其 FixedUpdate 在每一固定帧被调用。
OnEnable:当对象变为可用或激活状态时此函数被调用。
OnDisable:当对象变为不可用或非激活状态时此函数被调用。
OnDestroy:当MonoBehaviour将被销毁时,这个函数被调用。
其他情况:
编辑器(Editor)
Reset:Reset函数被调用来初始化脚本属性当脚本第一次被附到对象上,并且在Reset命令被使用时也会调用。
编者注:Reset是在用户点击Inspector面板上Reset按钮或者首次添加该组件时被调用。Reset最常用于在见识面板中给定一个默认值。
第一次场景加载(First Scene Load)
这些函数会在一个场景开始(场景中每个物体只调用一次)时被调用。
Awake:这个函数总是在任何Start()函数之前一个预设被实例化之后被调用,如果一个GameObject是非激活的(inactive),在启动期间Awake函数是不会被调用的直到它是活动的(active)。
OnEnable:只有在对象是激活(active)状态下才会被调用,这个函数只有在object被启用(enable)后才会调用。这会发生在一个MonoBehaviour实例被创建,例如当一个关卡被加载或者一个带有脚本组件的GameObject被实例化。
注意:当一个场景被添加到场景中,所有脚本上的Awake()和OnEable()函数将会被调用在Start()、Update()等它们中任何函数被调用之前。自然的,当一个物体在游戏过程中被实例化时这不能被强制执行。
第一帧更新之前(Before the first frame update)
Start:只要脚本实例被启用了Start()函数将会在Update()函数第一帧之前被调用。
对于那些被添加到场景中的物体,所有脚本上的Start()函数将会在它们中任何的Update()函数之前被调用,自然的,当一个物体在游戏过程中被实例化时这不能被强制执行。
在帧之间(In between frames)
OnApplicationPause:这个函数将会被调用在暂停被检测有效的在正常的帧更新之间的一帧的结束时。在OnApplicationPause被调用后将会有额外的一帧用来允许游戏显示显示图像表示在暂停状态下。
更新顺序(Update Order)
当你在跟踪游戏逻辑和状态,动画,相机位置等的时候,有几个不同的事件函数你可以使用。常见的模式是在Update()函数中执行大多数任务,但是也有其它的函数你可以使用。
FixedUpdate: FixedUpdate函数经常会比Update函数更频繁的被调用。它一帧会被调用多次,如果帧率低它可能不会在帧之间被调用,就算帧率是高的。所有的图形计算和更新在FixedUpdate之后会立即执行。当在FixedUpdate里执行移动计算,你并不需要Time.deltaTime乘以你的值,这是因为FixedUpdate是按真实时间,独立于帧率被调用的。
Update: Update每一帧都会被调用,对于帧更新它是主要的负荷函数。
LateUpdate:LateUpdate会在Update结束之后每一帧被调用,任何计算在Update里执行结束当LateUpdate开始时。LateUpdate常用为第三人称视角相机跟随。
渲染(Rendering)
OnPreCull: 在相机剔除场景前被调用。剔除是取决于哪些物体对于摄像机是可见的,OnPreCull仅在剔除起作用之前被调用。
OnBecameVisible/OnBecameInvisible:当一个物体对任意摄像机变得可见/不可见时被调用。
OnPreRender:在摄像机开始渲染场景之前调用。
OnRenderObject:在指定场景渲染完成之后调用,你可以使用GL类或者Graphics.DrawMeshNow 来绘制自定义几何体在这里。
OnPostRender:在摄像机完成场景渲染之后调用。
OnRenderImage(Pro Only):在场景徐然完成之后允许屏幕图像后期处理调用。
OnGUI:为了响应GUI事件,每帧会被调用多次(一般最低两次)。布局Layout和Repaint事件会首先处理,接下来处理的是是通过
Layout和键盘/鼠标事件对应的每个输入事件。
OnDrawGizmos:用于可视化的绘制一些小玩意在场景视图中。
协同程序(Coroutines)
正常的协同程序更新是在Update函数返回之后运行。一个协同程序是可以暂停执行(yield)直到给出的依从指令(YieldInstruction )完成,写成的不同运用:
yield:在所有的Update函数都已经被调用的下一帧该协程将持续执行。
yield WaitForSeconds:一段指定的时间延迟之后继续执行,在所有的Update函数完成调用的那一帧之后。
yield WaitForFixedUpdate:所有脚本上的FixedUpdate函数已经执行调用之后持续。
yield WWW:在WWW下载完成之后持续。
yield StartCoroutine:协同程序链,将会等到MuFunc函数协程执行完成首先。
销毁(When the Object is Destroyed)
OnDestory:这个函数在会在一个对象销毁前一帧调用,会在所有帧更新一个对象存在的最后一帧之后执行,对象也许会响应Object.Destroy 或一个场景关闭时被销毁。
退出游戏(When Quitting)
这些函数会在你场景中所有的激活的物体上调用:
OnApplicationQuit:这个函数在应用退出之前的所有游戏物体上调用,在编辑器(Editor)模式中会在用户停止PlayMode时调用,在网页播放器(web player)中会在网页视图关闭时调用。
OnDisable:当行为变为非启用(disable)或非激活(inactive)时调用。
下面用一张图来更形象地说明一下这几个类的在MonoBehaviour的生命周期中是如何被调用的:
官方给出的脚本中事件函数的执行顺序如下图:


Unity系统自带函数:
using UnityEngine;
using System.Collections; public class test : MonoBehaviour
{ void Awake()
{
print("Awake");
} void OnEnable()
{
print("OnEnable");
} void Start()
{
print("Start");
} void Update()
{
print("Update");
} void LateUpdate()
{
print("LateUpdate");
} void OnGUI()
{
print("OnGUI");
} void OnDestroy()
{
print("OnDestroy");
} void OnDisable()
{
print("OnDisable");
}
}
自带函数执行顺序如下:
运行时:
结束时:
会发现结束的时候比运行时多两个方法,OnDisable和OnDestroy,以上就是函数执行的顺序!
脚本的编译顺序
关于脚本的编译顺序很是头疼,官方的说法有点模糊,请看官方的解释: 
由于脚本的编译顺序会涉及到特殊文件夹,比如上面提到的Plugins、Editor还有Standard Assets等标准的资源文件夹,所以脚本的放置位置就非常重要了。下面用一个例子来说明不同文件夹中的脚本的编译顺序: 
如果在你的项目中建立如上图所示的文件夹层次结构时,编译项目之后会在项目文件夹中生成一些文件名中包含Editor、firstpass这些字样的项目文件。比如按照上图的文件夹结构,我们打开项目文件夹来看一下产生的项目文件是什么样的? 
1、首先从脚本语言类型来看,Unity3d支持3种脚本语言,都会被编译成CLI的DLL
如果项目中包含有C#脚本,那么Unity3d会产生以Assembly-CSharp为前缀的工程,名字中包含”vs”的是产生给Vistual Studio使用的,不包含”vs”的是产生给MonoDevelop使用的。
项目中的脚本语言 工程前缀 工程后缀 C# Assembly-CSharp csproj UnityScript Assembly-UnityScript unityproj Boo Assembly-Boo booproj
如果项目中这三种脚本都存在,那么Unity将会生成3种前缀类型的工程。
2、对于每一种脚本语言,根据脚本放置的位置(其实也部分根据脚本的作用,比如编辑器扩展脚本,就必须放在Editor文件夹下),Unity会生成4中后缀的工程。其中的firstpass表示先编译,Editor表示放在Editor文件夹下的脚本。
在上面的示例中,我们得到了两套项目工程文件:分别被Virtual Studio和MonoDevelop使用(后缀包不包含vs),为简单起见,我们只分析vs项目。得到的文件列表如下:
Assembly-CSharp-filepass-vs.csproj
Assembly-CSharp-Editor-filepass-vs.csproj
Assembly-CSharp-vs.csproj
Assembly-CSharp-Editor-vs.csproj
根据官方的解释,它们的编译顺序如下:
(1)所有在Standard Assets、Pro Standard Assets或者Plugins文件夹中的脚本会产生一个Assembly-CSharp-filepass-vs.csproj文件,并且先编译;
(2)所有在Standard Assets/Editor、Pro Standard Assets/Editor或者Plugins/Editor文件夹中的脚本产生Assembly-CSharp-Editor-filepass-vs.csproj工程文件,接着编译;
(3)所有在Assets/Editor外面的,并且不在(1),(2)中的脚本文件(一般这些脚本就是我们自己写的非编辑器扩展脚本)会产生Assembly-CSharp-vs.csproj工程文件,被编译;
(4)所有在Assets/Editor中的脚本产生一个Assembly-CSharp-Editor-vs.csproj工程文件,被编译。
之所以按照这样建立工程并按此顺序编译,也是因为DLL间存在的依赖关系所决定的。
Unity3D_02_基类MonoBehaviour/自带函数以及脚本执行的生命周期的更多相关文章
- Unity------Unity 脚本基类 MonoBehaviour 与 GameObject 的关系
Unity 脚本基类 MonoBehaviour 与 GameObject 的关系 标签: unity脚本 2017-03-27 12:55 395人阅读 评论(0) 收藏 举报 分类: Unity ...
- legend---六、php脚本变量的生命周期是怎样的
legend---六.php脚本变量的生命周期是怎样的 一.总结 一句话总结:应该是脚本结束变量的生命周期就完了 1.外部js找不到元素是怎么回事? 1 function myDailyTaskFin ...
- 【Unity3D基础教程】给初学者看的Unity教程(二):所有脚本组件的基类 -- MonoBehaviour的前世今生
作者:王选易,出处:http://www.cnblogs.com/neverdie/ 欢迎转载,也请保留这段声明.如果你喜欢这篇文章,请点[推荐].谢谢! 引子 上一次我们讲了GameObject,C ...
- [Unity2D]脚本基类MonoBehaviour介绍
Unity中的脚本都是继承自MonoBehaviour. MonoBehaviour 表示一个单一的行为.Unity中用户对游戏对象的操作被分割成若干个单一行为.每个单一行为都作为一个MonoBeha ...
- Unity编程标准导引-3.1 Component 组件脚本及其基本生命周期
本文为博主原创文章,欢迎转载,请保留出处:http://blog.csdn.net/andrewfan 3.1组件 Component 组件是Unity中最核心的一个概念,它是一切编程的基础.没有组件 ...
- java之线程(线程的创建方式、java中的Thread类、线程的同步、线程的生命周期、线程之间的通信)
CPU:10核 主频100MHz 1核 主频 3GHz 那么哪一个CPU比较好呢? CPU核不是越多越好吗?并不一定.主频用于衡量GPU处理速度的快慢,举个例子10头牛运送货物快还是1架飞机运 ...
- IronPython中共享的C#基类如何向下转型
在项目中,我们使用IronPython来定义工作流脚本来以应对科研多变的需求.项目使用的主要语言仍然是C#,使用C#封装了各种基础服务与基础设施.Python脚本只使用C#提供的服务,或者说只定义了逻 ...
- C++ - 虚基类、虚函数与纯虚函数
虚基类 在说明其作用前先看一段代码 class A{public: int iValue;}; class B:public A{public: void bPrintf(){ ...
- 使用虚幻引擎中的C++导论(二-UE4基类)
使用虚幻引擎中的C++导论(二) 第一,这篇是我翻译的虚幻4官网的新手编程教程,原文传送门,有的翻译不太好,但大体意思差不多,请支持我O(∩_∩)O谢谢. 第二,某些细节操作,这篇文章省略了,如果有不 ...
随机推荐
- 简单设计企业级JOB平台
前言 在企业级项目中有许多能够用到定时任务的场景例如: 在某个时间点统一给某些用户发送邮件信息 接口表数据发送 某月某日更新报表数据 ...... 目前我们使用SpringBoot快速整合Quartz ...
- 用xshell链接虚拟机上的linux
[步骤]一.安装VMware直接点击下一步即可 二.安装linux下载CentOS,在VMware中安装,这个网上有很多教程,这里就不赘述了. 三.配置要想连接上xshell,需要配置IP,将Linu ...
- C# 基于NPOI+Office COM组件 实现20行代码在线预览文档(word,excel,pdf,txt,png)
由于项目需要,需要一个在线预览office的功能,小编一开始使用的是微软提供的方法,简单快捷,但是不符合小编开发需求, 就另外用了:将文件转换成html文件然后预览html文件的方法.对微软提供的方法 ...
- 8.7 day28 网络编程 socket套接字 半连接池 通信循环 粘包问题 struct模块
前置知识:不同计算机程序之间的数据传输 应用程序中的数据都是从程序所在计算机内存中读取的. 内存中的数据是从硬盘读取或者网络传输过来的 不同计算机程序数据传输需要经过七层协议物理连接介质才能到达目标程 ...
- 使用webpack---安装webpack和webpack-dev-server
1.先确保安装了最新版的Node.js和NPM,并已经了解NPM的基本用法 (以下使用cmd命令行进行) 2.安装webpack (1)全局安装 $ npm install webpack -g ...
- Docker 方式部署 Solo 博客系统总结
此篇为Docker部署方式,另有Tomcat部署方式,请参考文章<Tomcat 方式部署 Solo 博客系统总结> 最近搭建了一个博客系统,作为自己的主页,方便记录一些平时所见所闻 ...
- Python 命令行之旅 —— 深入 argparse (一)
作者:HelloGitHub-Prodesire HelloGitHub 的<讲解开源项目>系列,项目地址:https://github.com/HelloGitHub-Team/Arti ...
- 快速了解Python并发编程的工程实现(下)
关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. Github:https:/ ...
- 「每日五分钟,玩转JVM」:线程共享区
前言 上一篇中,我们了解了JVM中的线程独占区,这节课我们就来了解一下JVM中的线程共享区,JVM中的线程共享区是跟随JVM启动时一起创建的,包括堆(Heap)和方法区()两部分,而线程独占区的程序计 ...
- vue-cli2.X中引入高德地图,将其设为全局对象
平时一般未用脚手架构建或用webpack构建的项目只要用script标签引入即可,在vue-cli 2.X构建的项目中,需要用如下方式引入高德地图: 首先在高德地图开放平台中注册开发者账号并获取key ...