【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这个目录下的所有文件都会被打包到发布版本中,程序可以通过文件路径来访问它们.这 ...
随机推荐
- 项目实战:rsync+sersync实现数据实时同步
一.组网介绍 本次实验使用两台主机: qll251 角色:Rsync server + Sersync server qll252 角色: Rsync client 本次实验采用CentOS7.7系统 ...
- Linux系统常用命令速查手册
点击上方"开源Linux",选择"设为星标" 回复"学习"获取独家整理的学习资料! 系统信息 arch #显示机器的处理器架构(1 ...
- Java安全之SnakeYaml反序列化分析
Java安全之SnakeYaml反序列化分析 目录 Java安全之SnakeYaml反序列化分析 写在前面 SnakeYaml简介 SnakeYaml序列化与反序列化 常用方法 序列化 反序列化 Sn ...
- Docker容器(container)详解 (转载自http://c.biancheng.net/view/3150.html)
- MySQL UNION 操作符用于连接两个以上的 SELECT 语句的结果组合到一个结果集合中
union 会删除重复数据 union all 不会删除重复数据 select * from ( select *,'a' as kind from tablea where name is not ...
- 解决 youtube 片尾内容被遮挡
参考: https://www.pcdvd.com.tw/showthread.php?t=1137333 在 ublock 的自定义静态规则中加上这句话 www.youtube.com##.ytp- ...
- 由C# dynamic是否装箱引发的思考
前言 前几天在技术群里看到有同学在讨论关于dynamic是否会存在装箱拆箱的问题,我当时第一想法是"会".至于为啥会有很多人有这种疑问,主要是因为觉得dynamic可能是因为有点特 ...
- python常用标准库(math数学模块和random随机模块)
常用的标准库 数学模块 import math ceil -- 上取整 对一个数向上取整(进一法),取相邻最近的两个整数的最大值. import math res = math.ceil(4.1) p ...
- linux篇-linux LAMP yum版安装
LAMP(linux.apache.mysql.php),是四个套件的合成,简单讲就是要把php运行在linux上,需要依赖apache和mysql数据库. 1 准备好一个linux系统(centos ...
- MongoDB 主节点的选举原则
每日一句 Life is like a shower. One wrong turn and you're in hot water. 生活就像淋浴,方向转错,水深火热. 概述 MongoDB在副本集 ...