【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这个目录下的所有文件都会被打包到发布版本中,程序可以通过文件路径来访问它们.这 ...
随机推荐
- clion 预编译文件的查看
看了一圈网上也没有我能一下就能看的懂的配置教程 我就手打一篇给在用clion的同学来参考一下 本文适用于g++编译 cmake Ninja生成器 clion 默认使用的是CMAKE来构建程序 生成器用 ...
- JS中的 && 、|| 、??、?. 运算符
javascript有不少好用的运算符,合理的使用可以大大提高工作效率,以下简单介绍了4种,具体如下: && 逻辑与运算(&&)是 AND 布尔操作.只有两个操作数都为 ...
- 电机噪声之谐波分析(内附simulink中FFT分析的相关参数配置与解析)
电机噪声之谐波分析(内附simulink中FFT分析的相关参数配置与解析) 目录 电机噪声之谐波分析(内附simulink中FFT分析的相关参数配置与解析) 写在前面 正文 电机噪声 谐波的产生 什么 ...
- 前后端分离,SpringBoot如何实现验证码操作
验证码的功能是防止非法用户恶意去访问登录接口而设置的一个功能,今天我们就来看看在前后端分离的项目中,SpringBoot是如何提供服务的. SpringBoot版本 本文基于的Spring Boot的 ...
- yarn/npm 设置镜像地址
注意 如果开发 electron 桌面软件,需要设置以下两个镜像地址 disturl.electron_mirror 如果用到了 node-sass 需要设置以下一个镜像地址 sass_binary_ ...
- linux篇-linux下源码安装nginx
LNMP模式 后续继续更新,先搭建nginx 安装环境gcc gcc-c++ 2 下载源码包解压 配置第一个报错 安装openssl openssl-devel yum -y install open ...
- shellcode编写
shellcode编写 shellcode是一段用于利用软件漏洞而执行的代码,通常使用机器语言编写,其目的往往是让攻击者获得目标机器的命令行shell而得名,其他有类似功能的代码也可以称为shellc ...
- JVM的类加载过程
每日一句 人到情多情转薄,而今真个不多情. 每日一句 The frog in the well knows nothing of the great ocean. 井底之蛙,不知大海. JVM 的类加 ...
- 注意:Spring Boot 2.7开始spring.factories不推荐使用了,接下来这么玩...
如果你是Spring Boot用户的话,一定有这样的开发体验,当我们要引入某个功能的时候,只需要在maven或gradle的配置中直接引入对应的Starter,马上就可以使用了,而不需要像传统Spri ...
- 基于.NetCore开发博客项目 StarBlog - (11) 实现访问统计
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...