一、了解帧的概念

游戏的本质就是一个死循环

每一次循环都会处理游戏逻辑 并 更新一次游戏画面

之所以能看到画面在动 是因为

切换画面速度达到一定速度时

人眼就会认为画面是动态且流畅的

一帧就是执行了一次循环

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...)的更多相关文章

  1. Shell编程(二)——shell的基础知识及常用命令

    shell的基础知识 一.bash有以下特点: 1.记录命令历史 2.指令和文件名补全 3.别名 alias rm='rm -i' 4.通配符 * 0个或多个字符 ?​匹配一个字符 5 输入输出重定向 ...

  2. 【Unity基础知识】基础游戏单位GameObject中常用的属性和API

    一.GameObject中的成员变量 主要思想:得到该脚本依附的GameObject的相关信息 现有: Lesson4的代码: using System.Collections; using Syst ...

  3. Unity基础知识学习笔记一

      1,Unity 4.5.4这个版本,在打包ios应用程序的时候.会生成一个xcode工程,但是这个工程无法在xcode6上变异,无法生成ios8上发布.所以unity在ios8发布3天内就发了4. ...

  4. Unity基础知识学习笔记二

    1,object Instantiate(object original,Vector3 position,Quaternion rotation)       克隆原始物体,并返回克隆物体.     ...

  5. loadrunder之脚本篇——脚本基础知识和常用操作

    1)编码工具设置 自动补全输入Tools->General Options->Environment->Auto complete word 显示功能语法Tools->Genr ...

  6. Hive HiveQL基础知识及常用语句总结

    基础语句 CREATE DROP 建表.删表 建表 -------------------------------------- -- 1. 直接建表 ------------------------ ...

  7. MySQL基础知识和常用命令总结

    说明:以下内容是阅读书籍<<MySQL必知必会>>的摘要和总结 检索数据 排序检索数据 过滤数据 使用通配符过滤 使用正则表达式进行搜索 创建计算字段 使用数据处理函数 汇总数 ...

  8. Git基础知识与常用命令

    一:相关概念: 1:工作区(Working Directory): 就是你在电脑里能看到的目录 2:版本库(Repository): 工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库. ...

  9. 【Unity基础知识之三】Unity Assets目录下的特殊文件夹名称

    Unity3D的特殊目录名称   Unity预留了一些目录名称,这些目录有着特殊的含义.比较重要的有: Resources这个目录下的所有文件都会被打包到发布版本中,程序可以通过文件路径来访问它们.这 ...

随机推荐

  1. 为什么建议大家使用 Linux 开发?

    关注「开源Linux」,选择"设为星标" 回复「学习」,有我为您特别筛选的学习资料~ Linux 能用吗? 我身边还有些朋友对 linux 的印象似乎还停留在黑乎乎的命令行界面上. ...

  2. ShardingSphere 集成 CosId 实战

    背景 在软件系统演进过程中,随着业务规模的增长 (TPS/存储容量),我们需要通过集群化部署来分摊计算.存储压力. 应用服务的无状态设计使其具备了伸缩性.在使用 Kubernetes 部署时我们只需要 ...

  3. 实践GoF的23种设计模式:建造者模式

    摘要:针对这种对象成员较多,创建对象逻辑较为繁琐的场景,非常适合使用建造者模式来进行优化. 本文分享自华为云社区<[Go实现]实践GoF的23种设计模式:建造者模式>,作者: 元闰子. 简 ...

  4. 【高并发】通过源码深度解析ThreadPoolExecutor类是如何保证线程池正确运行的

    大家好,我是冰河~~ 对于线程池的核心类ThreadPoolExecutor来说,有哪些重要的属性和内部类为线程池的正确运行提供重要的保障呢? ThreadPoolExecutor类中的重要属性 在T ...

  5. 为什么说 Gradle 是 Android 进阶绕不去的坎 —— Gradle 系列(1)

    请点赞,你的点赞对我意义重大,满足下我的虚荣心. Hi,我是小彭.本文已收录到 GitHub · Android-NoteBook 中.这里有 Android 进阶成长知识体系,有志同道合的朋友,欢迎 ...

  6. 强制20天加班开发app后被集体解雇,象寻技术负责人公众号发文怒斥前领导

    5月16日下午三点,象寻官方公众号发了一篇<祝象寻早日倒闭的文章>文章,文章配一个竖中指的手势.如此劲爆的文章瞬间引爆了微信朋友圈,大家纷纷分享给好友和微信群,阅读量也达到了十万+. 当时 ...

  7. 766. Toeplitz Matrix - LeetCode

    Question 766. Toeplitz Matrix Solution 题目大意: 矩阵从每条左上到右下对角线上的数都相等就返回true否则返回false 思路: 遍历每一行[i,j]与[i+1 ...

  8. 手绘图解java类加载原理

    摘要:这也许是全网"最大"."最细"."最深"的java类加载原理图解了. 本文分享自华为云社区<[读书会第12期]这也许是全网&qu ...

  9. Fail2ban 配置详解 基础配置(fail2ban.conf)

    [Definition] loglevel = INFO # 设置日志级别:级别越低显示日志的信息更详细. # CRITICAL - 关键级别 # ERROR - 错误级别 # WARNING - 警 ...

  10. uniapp设置竖屏

    //在APP.vue中的onLaunch钩子写入plus.screen.lockOrientation('portrait-primary');