Unity基础-01


SerializeField属性

在Unity中,[SerializeField] 是一个属性(Attribute),它的主要作用是 让私有字段(private field)可以在 Unity Inspector 面板中显示和编辑,同时保持其封装性(不需要将字段设置为public)。

以下是它的详细功能和作用:


作用

  1. 显示私有字段: 默认情况下,private 字段是不可见的。但是通过在字段前加上 [SerializeField],可以让 Unity 将其序列化,从而使它出现在 Inspector 面板中。
  2. 控制访问权限: 如果字段直接定义为 public,虽然可以在 Inspector 中编辑,但这种做法会暴露字段,可能导致脚本设计不够安全或灵活。而 [SerializeField] 允许字段保持私有,增强了封装性,遵循了面向对象编程的最佳实践。
  3. 序列化: Unity 会将带有 [SerializeField] 标记的字段序列化(保存到场景文件或预制体文件中),从而在运行时或重新加载场景时恢复它们的值。

使用方式

示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
using UnityEngine;

public class Example : MonoBehaviour
{
[SerializeField]
private int privateInt = 10; // 这个字段会出现在 Inspector 中

public int publicInt = 20; // 默认显示在 Inspector 中

private float privateFloat = 30f; // 不会显示在 Inspector 中
}

运行上面的代码后,privateInt 会显示在 Inspector 中,而 privateFloat 不会显示。此外,publicInt 即使没有标记,也会显示在 Inspector 中(因为 Unity 默认序列化 public 字段)。


注意事项

  1. 序列化规则: Unity 支持的序列化类型包括:

    • 基本类型:int, float, bool, string 等。
    • Unity 类型:Vector3, Color, Transform, GameObject 等。
    • 自定义类/结构:只要它们是 Serializable(即用 [System.Serializable] 标记的类/结构)。

    不支持的类型:

    • 字典(Dictionary
    • 动态类型(如 List<object> 或包含非序列化类型的容器)
  2. 字段的可见性和编辑性:

    • 即使字段显示在 Inspector 中,它的值在运行时仍然只能通过脚本访问,除非定义了公共方法。
    • 如果不希望字段被误修改,可以配合 readonly 使用,但需要通过代码赋值。
  3. 常见问题:

    • 忘记赋初始值:如果没有初始化 [SerializeField] 字段,它们会被赋默认值(如 0null)。
    • 多脚本编辑器同步:如果字段值在 Inspector 中更改,记得保存场景或预制体文件以避免丢失修改。

public 的比较

特性 [SerializeField] + private public
Inspector 显示 显示 显示
访问权限 私有(需通过方法访问) 公有(可直接访问)
封装性 更好 较差
序列化 支持 支持

总结

  • [SerializeField] 保持字段私有,同时允许在 Inspector 中编辑,适合需要控制字段访问权限的场景。
  • 遵循“字段私有化、通过方法或属性访问”的良好编码习惯。
  • [HideInInspector](隐藏字段)或 NonSerialized(不序列化字段)结合使用,可以灵活管理字段的显示和保存行为。

Time.deltatime

Time.deltaTime 的概念

在Unity中,Time.deltaTime 是一个每帧所耗时间的变量,它表示上一帧和当前帧之间的时间间隔,单位是秒。

主要用途

Time.deltaTime 常用于以下场景:

  1. 平滑动画或移动
    它保证了物体的移动、动画等行为是与帧率无关的。无论帧率快(60帧/秒)还是慢(30帧/秒),物体的移动速度或动画的进程都会保持一致。
  2. 计算随时间变化的行为
    例如:物体移动距离、旋转角度、UI动画等。

核心原理

游戏的运行分为若干帧(Frame),每一帧都需要时间来完成渲染和逻辑计算。如果游戏帧率不同(FPS=Frames Per Second),每帧之间的时间间隔也会不同。

公式解释

假设一个物体每秒移动 5个单位

  • 如果帧率是 60FPS(每秒60帧),每帧的时间间隔大约是 1/60 ≈ 0.016秒
  • 如果帧率是 30FPS(每秒30帧),每帧的时间间隔大约是 1/30 ≈ 0.033秒

在帧率波动的情况下,Time.deltaTime 提供了当前帧的准确时间间隔,确保物体的运动速率符合预期。例如,使用公式:

1
移动距离 = 移动速度(单位/秒) * Time.deltaTime

这样无论帧率如何,物体都能以一致的速度移动。


使用示例

1. 基本移动

让一个物体以 5单位/秒 的速度沿着X轴移动:

1
2
3
4
5
void Update()
{
float speed = 5f; // 移动速度(单位/秒)
transform.Translate(Vector3.right * speed * Time.deltaTime);
}

如果 Time.deltaTime 是 0.016(60FPS),单帧移动距离为:

1
移动距离 = 5 * 0.016 = 0.08单位

2. 平滑旋转

让物体每秒绕Y轴旋转 90度:

1
2
3
4
5
void Update()
{
float rotationSpeed = 90f; // 每秒旋转的角度
transform.Rotate(Vector3.up, rotationSpeed * Time.deltaTime);
}

3. 计时器

实现一个倒计时器:

1
2
3
4
5
6
7
8
9
10
float timer = 10f; // 初始倒计时时间

void Update()
{
timer -= Time.deltaTime; // 随时间减少
if (timer <= 0)
{
Debug.Log("时间到!");
}
}

注意事项

  1. 仅适用于基于帧的更新方法
    Time.deltaTime 通常在 Update()LateUpdate() 方法中使用,因为这些方法每帧执行一次。

  2. FixedUpdate 中使用 Time.fixedDeltaTime
    如果是在物理模拟中(如 Rigidbody 的移动或力的施加),应使用 Time.fixedDeltaTime,它是固定时间间隔(默认值为0.02秒,表示50FPS)。例如:

    1
    2
    3
    4
    void FixedUpdate()
    {
    rb.MovePosition(rb.position + Vector3.forward * speed * Time.fixedDeltaTime);
    }
  3. 帧率过低时的影响
    当帧率过低(例如低于15FPS),Time.deltaTime 的值会变得较大,可能导致物体的移动速度显得不够流畅。需要结合最大步长限制来避免这种问题。


总结

Time.deltaTime 是Unity中一个关键的时间变量,用于处理与时间相关的行为,使得游戏逻辑与帧率无关。通过它,开发者可以确保动画、移动、旋转等效果在不同设备和帧率下都保持一致,是游戏开发中不可或缺的一部分工具。


文章作者: 懒惰
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 懒惰 !
  目录