【Unity基础知识】认识常用的生命周期函数(Awake、Start、Update...)
一、了解帧的概念
游戏的本质就是一个死循环
每一次循环都会处理游戏逻辑 并 更新一次游戏画面
之所以能看到画面在动 是因为
切换画面速度达到一定速度时
人眼就会认为画面是动态且流畅的
一帧就是执行了一次循环
Unity底层已经封装好了这个死循环
我们只需要利用Unity的生命周期函数的规则来执行游戏逻辑即可
FPS(Frames Per Second)
即每秒钟帧数
一般我们说60帧30帧
意思是1秒更新60次、30次画面
1s = 1000ms
60帧:1帧为 1000ms/60 ≈ 16.66ms
30帧:1帧为 1000ms/30 ≈ 33.33ms
游戏卡顿的原因:
跑1帧游戏逻辑的计算量过大,或者硬件性能过低,无法在一帧的时间内处理完所有游戏逻辑
二、生命周期函数的概念
所有继承MonoBehavior的脚本 最终都会挂载到GameObject游戏对象上
生命周期函数就是该脚本对象依附的GameObject对象从出生到消亡整个生命周期中
会通过反射自动调用的一些特殊函数
Unity帮助我们记录了一个GameObject对象依附了哪些脚本
会自动地得到这些对象,通过反射去执行一些固定名字的函数(就是生命周期函数)
三、生命周期函数
注意:
生命周期函数的访问修饰符一般为private和protected
因为不需要在外部手动调用生命周期函数,都是Unity自动帮我们调用

3-1.Awake
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson1 : MonoBehaviour
{
//当一个对象(自己这个类对象 而不是依附的GameObject)被创建时,会调用该生命周期函数
//作用:Awake是类似构造函数的存在,我们可以在一个类对象刚被创建时,进行一些初始化操作
//Awake只会被执行一次
private void Awake()
{
//补充知识点:在Unity中打印信息的两种方式
//1.如果没有继承MonoBehaviour,可以使用debug.Log();
Debug.Log("我是打印的信息");
Debug.LogWarning("警告!");
Debug.LogError("出错了!");
//2.如果继承了MonoBehaviour 有一个现成的方法可以实现打印
print("我是打印的信息");
}
}
3-2.OnEnable
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson1 : MonoBehaviour
{
//依附的GameObject对象每次被激活时 会被调用
//作用:想要当一个对象被激活时 进行一些逻辑处理,就可以写在本函数中
private void OnEnable()
{
print("我依附的GameObject被激活了");
}
}

3-2.Start
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson1 : MonoBehaviour
{
//从自己被创建出来后,第一次帧更新之前被调用
//作用:还是用于初始化信息的,但是它相对Awake来说,要执行的晚一些
// 因为它是在对象进行帧更新之前才会被执行
//一个对象只会调用一次
private void Start()
{
print("我在第1帧更新前被执行");
}
}
3-4.FixedUpdate
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson1 : MonoBehaviour
{
//固定间隔时间执行,间隔的时间可以设置
//作用:用于进行物理相关的更新(如碰撞检测)
// 它是每一帧都会执行的,但是这里的帧和游戏帧有点不同
private void FixedUpdate()
{
print("我会固定间隔时间循环执行");
}
}


3-5.Update
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson1 : MonoBehaviour
{
//逻辑帧更新
//每秒更新多少次是可以设置的,如果不设置 默认会以最快的速度更新
//作用:用于处理游戏核心逻辑更新
private void Update()
{
print("我一帧被执行一次");
}
}
3-6.LateUpdate
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson1 : MonoBehaviour
{
//每帧执行 于Update之后执行
//作用:一般用来处理摄像机位置更新相关内容
// 在Update和LateUpdate之间,Unity进行了一些处理,处理动画相关的更新
private void LateUpdate()
{
print("我每针都会被执行,但晚于Update");
}
}
3-7.OnDisable
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson1 : MonoBehaviour
{
//依附的GameObject对象每次失活时被调用(对象被销毁时也会被调用)
//作用:想要当一个对象失活时 进行一些逻辑处理,就可以写在本函数中
private void OnDisable()
{
print("我依附的GameObject失活了");
}
}

3-8.OnDestroy
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson1 : MonoBehaviour
{
//对象被销毁时被调用(依附的GameObject对象被删除时)
private void OnDestroy()
{
print("我被销毁了");
}
}
四、生命周期函数支持继承和多态

Lesson1的脚本如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson1 : MonoBehaviour
{
//把Awake写成一个虚函数
protected virtual void Awake()
{
print("父类的Awake");
}
}
Lesson1Son的脚本如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson1Son : Lesson1
{
//可以重写父类Lesson1的虚函数
protected override void Awake()
{
base.Awake();
print("子类的Awake");
}
}

运行:可以看到,父类的Awake和子类的Awake都被执行了,所以生命周期函数支持继承和多态

五、补充:关于继承Mono的类的构造函数
要知道,虽然不建议在继承MonoBehavior的类中写构造函数
但是不意味着不能写,当在继承MonoBehavior的类中写无参构造函数时
会发现在编辑模式下或者运行后,只要该脚本挂载在场景中,那么该无参构造函数是会被自动执行
因为Unity的工作原理中提到的反射机制,实际上Unity通过反射帮助我们实例化了该脚本对象
既然要实例化那么肯定是需要new的,只不过Unity中不需要我们自己new继承了MonoBehavior的类,只要挂载后Unity就帮助我们做了这件事
那么为什么不建议继承MonoBehavior的类写构造函数呢?
1.Unity的规则就是,继承MonoBehavior的脚本不能new只能挂载
2.生命周期函数的Awake是类似构造函数的存在,当对象出生就会自动调用
3.写构造函数反而在结构上会破坏Unity设计上的规范
总结:
如果继承MonoBehavior的脚本想要进行初始化相关,可以在Awake或者Start中进行,搞清这两个生命周期函数的执行时机,根据需求选择在哪里进行初始化。
切记!!继承MonoBehavior的脚本不要new,不要new,不要new!!
六、补充:不同对象的声明周期函数是在同一个线程中执行的吗?
Unity中所有对象上挂载的生命周期函数都是在一个主线程中按先后执行的
Unity会主动把场景上的对象,对象上挂载的脚本都统统记录下来,
在主线程的死循环中,按顺序按时机的通过反射,执行记录的对象身上挂载的脚本的对应生命周期函数
【Unity基础知识】认识常用的生命周期函数(Awake、Start、Update...)的更多相关文章
- Shell编程(二)——shell的基础知识及常用命令
shell的基础知识 一.bash有以下特点: 1.记录命令历史 2.指令和文件名补全 3.别名 alias rm='rm -i' 4.通配符 * 0个或多个字符 ?匹配一个字符 5 输入输出重定向 ...
- 【Unity基础知识】基础游戏单位GameObject中常用的属性和API
一.GameObject中的成员变量 主要思想:得到该脚本依附的GameObject的相关信息 现有: Lesson4的代码: using System.Collections; using Syst ...
- Unity基础知识学习笔记一
1,Unity 4.5.4这个版本,在打包ios应用程序的时候.会生成一个xcode工程,但是这个工程无法在xcode6上变异,无法生成ios8上发布.所以unity在ios8发布3天内就发了4. ...
- Unity基础知识学习笔记二
1,object Instantiate(object original,Vector3 position,Quaternion rotation) 克隆原始物体,并返回克隆物体. ...
- loadrunder之脚本篇——脚本基础知识和常用操作
1)编码工具设置 自动补全输入Tools->General Options->Environment->Auto complete word 显示功能语法Tools->Genr ...
- Hive HiveQL基础知识及常用语句总结
基础语句 CREATE DROP 建表.删表 建表 -------------------------------------- -- 1. 直接建表 ------------------------ ...
- MySQL基础知识和常用命令总结
说明:以下内容是阅读书籍<<MySQL必知必会>>的摘要和总结 检索数据 排序检索数据 过滤数据 使用通配符过滤 使用正则表达式进行搜索 创建计算字段 使用数据处理函数 汇总数 ...
- Git基础知识与常用命令
一:相关概念: 1:工作区(Working Directory): 就是你在电脑里能看到的目录 2:版本库(Repository): 工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库. ...
- 【Unity基础知识之三】Unity Assets目录下的特殊文件夹名称
Unity3D的特殊目录名称 Unity预留了一些目录名称,这些目录有着特殊的含义.比较重要的有: Resources这个目录下的所有文件都会被打包到发布版本中,程序可以通过文件路径来访问它们.这 ...
随机推荐
- 五二不休息,今天也学习,从JS执行栈角度图解递归以及二叉树的前、中、后遍历的底层差异
壹 ❀ 引 想必凡是接触过二叉树算法的同学,在刚上手那会,一定都经历过题目无从下手,甚至连题解都看不懂的痛苦.由于leetcode不方便调试,题目做错了也不知道错在哪里,最后无奈的cv答案后心里还不断 ...
- 2021 CSP-J复赛 我的备战与游记
目录 备战 2021.10.18 2021.10.19 2021.10.20 2021.10.21 2021.10.22 比赛当日 早上 线下见面 正文 比赛后 赛后总结与讲解 简单总结 Candy ...
- 关于利用STL栈求解四则中缀表达式以及中缀表达式转逆波兰表达式和逆波兰表达式的求解
今天总结一下栈的一个重要应用---四则数学表达式的求解 数学表达式的求解是栈的一个重要的应用,在计算机的应用中 如果求解一个四则运算表达式,我们可能会直接写一个程序例如什么printf("% ...
- Java学习,利用IDEA开发工具连接redis
Idea连接redis及Jedis数据操作 注意是否开启了redis服务!!! 1.打开虚拟机终端,查看虚拟机防火墙是否关闭 查看防火墙当前状态命令: $sudo ufw status 我的是默认关闭 ...
- 移动应用开发迎来哪些新技术?5月24日相约HDD·线上沙龙·创新开发专场
HUAWEI Developer Day(简称HDD),是华为开发者联盟与广大开发者深度交流的平台.围绕移动终端的最新技术和产品形态,持续向广大开发者传递华为终端的最新产品和开放服务能力,结合最新的行 ...
- 其实 Gradle Transform 就是个纸老虎 —— Gradle 系列(4)
前言 目前,使用 AGP Transform API 进行字节码插桩已经非常普遍了,例如 Booster.神策等框架中都有 Transform 的影子.Transform 听起来很高大上,其本质就是一 ...
- 好客租房12-JSX的注意点
1.4注意点 1React元素的属性名使用驼峰式命名法 2特殊属性名 class-className for->htmlFor 3没有子节点可以用单标签表示 4使用小括号包裹jsx const ...
- css页面样式初始化
为什么? 同一个样式,在各个浏览器的默认样式可能不同,所以需要统一初始化,同一个页面在不同浏览器能正常显示. @charset "utf-8"; /*css reset*/ bod ...
- Java内存分析——JavaSE基础
内存分析 堆:存放new的对象和数组,可以被所有线程共享,不会存放别的对象引用 栈 存放基本变量类型(会包含这个基本类型的具体数值) 引用对象的变量(会存放这个引用在堆里的具体地址) 方法区(属于堆的 ...
- django框架1
简介 1.前端 与用户打交道的界面 2.web框架 可以将前端和数据库整合到一起 3.数据库 专门用于存储数据 内容概要 纯手撸web框架 基于wsgiref模块 优化措施 动静态网 ...