Unity学习90天-第2天-认识Unity生命周期函数并用 Update 控制物体移动,FixedUpdate 控制物理

欢迎回来! 今天我们来搞定 Unity 里一个必须掌握的核心概念------生命周期函数。 很多初学者在这里卡壳,学完这篇你就彻底懂了!

一、什么是生命周期函数?

你可以把一个 Unity 脚本想象成一个员工的职业生涯

复制代码
入职第一天   →   Awake()    背好工牌,认识自己的工位
开始上班     →   Start()    开晨会,了解今天的任务
每天上班     →   Update()   日常工作,每天都做
体检日       →   FixedUpdate()  固定时间做固定的事
下班前       →   LateUpdate()  收尾工作,等别人都做完再做
离职         →   OnDestroy()  交接工作,离开公司

这个比喻贯穿全文,记住它,生命周期就懂了

Awake --- "入职第一天"

cs 复制代码
void Awake()
{
    Debug.Log("游戏初始化")
}

Awake 做一件事:认识自己。

  • 脚本一创建,立刻执行,哪怕组件是关闭状态
  • 只跑一次
  • 这里做什么?获取自身组件、初始化自己的变量

常见错误:

  • 在 Awake 里去调用另一个脚本的数据。
  • 这很危险!因为你不知道对方的 Awake 有没有跑完。
  • 自己的事 Awake 做,依赖别人的事交给 Start!

Start --- "开始上班第一天"

cs 复制代码
void Start()
{
    Debug.Log("游戏开始,当前血量:" + hp);
}

Start 做一件事:和别人打招呼。

  • 第一帧 Update 之前执行
  • 此时所有脚本的 Awake 都已经跑完了
  • 只跑一次
  • 这里做什么?依赖其他脚本的初始化、打印调试信息

一句话区分 Awake 和 Start:

  • Awake → 管好自己
  • Start → 联系别人

Update --- "每天上班"

cs 复制代码
void Update()
{
    float h = Input.GetAxis("Horizontal");
    transform.Translate(Vector3.right * h * speed * Time.deltaTime);
}

Update 是你用得最多的函数,没有之一。

  • 每帧执行一次,游戏运行期间一直循环
  • 帧率是不固定的(手机可能 30fps,PC 可能 144fps)
  • 所以移动必须乘 Time.deltaTime,否则帧率越高跑得越快!

Update 适合做什么:

✅ 键盘 / 鼠标输入检测

✅ 直接修改 Transform 的移动

✅ UI 数值更新

✅ 计时器

❌ 物理运算(会抖!)

Time.deltaTime 是什么?

  • 就是上一帧到这一帧经过了多少秒
  • 60fps 时约等于 0.016 秒,30fps 时约等于 0.033 秒。
  • 乘上它之后,不管帧率高低,每秒移动距离都一样

FixedUpdate --- "固定体检日"

cs 复制代码
void FixedUpdate()
{
    rb.AddForce(Vector3.forward * 10f);
}

FixedUpdate 是专门给物理引擎准备的。

  • 固定时间间隔 执行,默认 0.02秒一次(50次/秒)
  • 和帧率完全无关
  • 不需要乘 Time.deltaTime(用 Time.fixedDeltaTime 如需要)

FixedUpdate 适合做什么:

✅ Rigidbody 施力 AddForce

✅ 物理驱动的移动 MovePosition

✅ 需要和碰撞体交互的运动

❌ 输入检测(会丢帧!按键可能被跳过)

为什么输入不能放 FixedUpdate?

假设游戏跑 60fps,Update 每帧都能检测到按键。但 FixedUpdate 只有 50次/秒,有些帧根本不执行,GetKeyDown 触发的瞬间可能直接被跳过!

LateUpdate --- "下班前收尾"

cs 复制代码
void LateUpdate()
{
    // 等物体移动完,摄像机再跟过来
    cam.position = transform.position + offset;
}

LateUpdate 是"等所有人做完我再做"。

  • 每帧执行,但在所有 Update 之后
  • 保证你看到的是"这帧结束时"的最终状态

LateUpdate 适合做什么:

✅ 摄像机跟随(最经典用法)

✅ 依赖其他脚本Update结果的逻辑

摄像机为什么要放 LateUpdate?

如果摄像机和角色都在 Update 里,执行顺序不确定,摄像机可能先跑 ,角色还没动,摄像机就已经跟了个寂寞。放 LateUpdate,角色动完,摄像机再跟,丝滑!

执行顺序总览

游戏启动

|

Awake()只跑一次

|

Start()只跑一次

|

游戏循环[ FixedUpdate()0.2秒执行一次,Update() 每帧执行,LateUpdate()每帧Update后]

|

OnDestroy() 销毁时,只跑一次

二、脚本实现

经过上面的所有学习之后那么我们来完成我们的脚本代码吧!

首先我们设置移动速度与跳跃高度

cs 复制代码
    [Header("移动参数")]
    public float moveSpeed = 5f;      // 移动速度

    [Header("物理参数")]
    public float jumpForce = 5f;      // 跳跃冲量

[Header] 是 Unity 的一个特性(Attribute),作用很简单:

在 Inspector 面板里,给变量分组加上标题文字。

然后我们在定义私有变量用于获取物理组件等

cs 复制代码
// 私有变量
private Rigidbody rb;             // 刚体组件引用
private Vector3 inputDir;         // 本帧的输入方向(Update写,FixedUpdate读)
private bool jumpRequest;         // 跳跃请求标记(Update写,FixedUpdate读)

接下来我们在初始化 Awake()获取我们的刚体组件,如果获取不到就向控制台发送信息

cs 复制代码
    void Awake()
    {
        rb = GetComponent<Rigidbody>();

        if (rb == null)
        {
            Debug.LogError("【PhysicsMoveDemo】请在该物体上添加 Rigidbody 组件!");
        }
    }

初始化完成后Start()我们也向控制台发送完成信息

cs 复制代码
    void Start()
    {
        Debug.Log("【Start】脚本初始化完成,初始位置:" + transform.position);
    }

在每帧运行时Update()我们都要获取我们的玩家键盘键输入并且实现移动和跳跃等逻辑

cs 复制代码
 void Update()
 {
     // --- 1. 读取键盘输入 ---
     float h = Input.GetAxis("Horizontal"); // A/D 左右
     float v = Input.GetAxis("Vertical");   // W/S 前后
     // normalized 防止斜向移动速度叠加变快(斜向本来是 √2 ≈ 1.41 倍)
     inputDir = new Vector3(h, 0, v).normalized;

     // --- 2. 非物理移动
     transform.Translate(inputDir * moveSpeed * Time.deltaTime, Space.World);

     // --- 3. 跳跃请求:GetKeyDown 必须在 Update 里检测,防止 FixedUpdate 漏帧 ---
     if (Input.GetKeyDown(KeyCode.Space))
     {
         jumpRequest = true; // 先记录请求,在 FixedUpdate 里执行
     }
 }

在这里先说明一下

非物理移动:直接操作 Transform(适合无 Rigidbody 的物体)

物理驱动移动:使用 MovePosition(比直接改 position 更稳定)

如果同时有 Rigidbody,Transform 和物理会冲突,二选一即可,现在这里写的是非物理移动

接下来我们就要编写物理帧执行的代码,比如物理移动,跳跃执行等

cs 复制代码
    void FixedUpdate()
    {
        // --- 1. 物理驱动移动
        // Time.fixedDeltaTime 固定为 0.02s,也可以不乘(效果一样,写上更规范)
        Vector3 nextPos = rb.position + inputDir * moveSpeed * Time.fixedDeltaTime;
        rb.MovePosition(nextPos);

        // --- 2. 执行跳跃:ForceMode.Impulse = 瞬间冲量,适合跳跃 ---
        if (jumpRequest)
        {
            rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
            jumpRequest = false; // 重置标记,防止连续跳
        }
    }

最后在所有 Update 执行完毕后LateUpdate()

cs 复制代码
    void LateUpdate()
    {
        // 此处预留摄像机跟随逻辑
        // 示例:Camera.main.transform.position = transform.position + new Vector3(0, 5, -8);
    }

接下来我们挂载脚本到物体上吧,别忘啦如果使用的是物理驱动的移动方式需要给物体加上刚体组件哦,接下来看运行结果

今天的内容就到这里! 接下来我将连续更新90天的Untiy教程从基础到一个网络部分,有兴趣的朋友们可以收藏关注,谢谢!如果有疑问,评论区见。

相关推荐
报错小能手2 小时前
ios开发方向——swift错误处理:do/try/catch、Result、throws
开发语言·学习·ios·swift
LX567772 小时前
传统销售如何系统学习成为AI智能销售顾问?认证指南
人工智能·学习
做cv的小昊3 小时前
【TJU】应用统计学——第五周作业(3.1 假设检验的基本思想、3.2 单个正态总体参数的假设检验)
学习·线性代数·机器学习·数学建模·矩阵·概率论·tju
格鸰爱童话3 小时前
向AI学习项目技能(六)
java·人工智能·spring boot·python·学习
H_老邪3 小时前
spring boot 学习之路-1.0
spring boot·后端·学习
东京老树根4 小时前
SAP学习笔记 - BTP SAP Build02 - Deploy,开始URL,Approve,Reject,履历确认,Log,Context
笔记·学习
头疼的程序员4 小时前
计算机网络:自顶向下方法(第七版)第九章 学习分享(一)
学习·计算机网络
小墨同学boy5 小时前
越用越强不是广告语:拆解 Hermes Agent 的三层学习机制
人工智能·学习
小林up5 小时前
【Unity URP源码阅读1】ColorGradingLUT
unity·游戏引擎