Unity:序列化(SerializeField)

发布于:2025-04-06 ⋅ 阅读:(40) ⋅ 点赞:(0)

目录

第一性原理:从最基本的需求开始

1. 什么是字段(Field)?为什么需要序列化?

2. [SerializeField]的基本作用

3. 为什么不直接用public?

4.序列化的原理

5. 更进一步:与public和private的区别

6 小结:第一性原理的核心

第一性原理:从最基本的需求开始

在编程中,尤其是游戏开发或Unity引擎中使用C#时,我们经常需要让程序中的某些数据(比如变量)在编辑器中可见,或者保存到磁盘上,以便在程序运行时或下次启动时恢复这些数据。这就是“序列化”(Serialization)的核心需求。

序列化本质上是为了解决一个问题:如何把程序中的数据(比如一个对象的状态)转换为可以保存或传输的形式? 反过来,反序列化则是把保存或传输的数据恢复成程序可以使用的状态。

在C#中,[SerializeField]是一个属性(Attribute),它的作用是告诉Unity或C#的序列化系统:“嘿,这个字段虽然是私有的或默认不可见的,但我希望你能序列化它,让它在编辑器中可见,或者保存到文件中。”

现在,我们来一步步拆解。

1. 什么是字段(Field)?为什么需要序列化?

首先,假设你在C#中写了一个类,里面有一些变量(字段),比如:

public class Player {
    private int health = 100; // 玩家的血量
    private string name = "Hero"; // 玩家的名字
}

这些字段默认是私有的(private),意思是其他代码不能直接访问它们。这种设计是为了保护数据安全。但在某些场景下,比如Unity游戏开发,你希望这些字段可以在Unity编辑器中调整,或者保存到场景文件中,这样游戏运行时就能加载这些值。

问题来了:私有的字段默认是不会被Unity或C#的序列化系统看到的,因为它们是“隐藏”的。那么怎么办?这就是[SerializeField]出场的地方。

2. [SerializeField]的基本作用

[SerializeField]是一个属性标记,你可以把它加在字段前面,告诉序列化系统:“即使这个字段是私有的(或公有的),我也想让它被序列化。” 通俗来说,就是“让这个字段‘暴露’出来”。

看个例子:

using UnityEngine;

public class Player : MonoBehaviour {
    [SerializeField]
    private int health = 100;

    [SerializeField]
    private string name = "Hero";
}

在这里,[SerializeField]的作用是:

  • 让health和name这两个私有的字段在Unity编辑器中可见。你可以直接在Inspector面板中看到它们,并且手动修改值。

  • 让这些字段的值可以在场景保存时被序列化,游戏下次加载时还能恢复这些值。

如果没有[SerializeField],因为health和name是私有的,Unity编辑器根本看不到它们,也无法保存它们的值。

3. 为什么不直接用public?

你可能会问:既然[SerializeField]可以让私有的字段暴露,为什么不直接把字段设为public呢?

这是个好问题!原因有几个:

  • 封装性(Encapsulation):在面向对象编程中,我们希望数据(字段)是私有的,只有通过特定的方法(比如getter和setter)才能访问或修改。这样可以防止代码的其他部分随意改动数据,增加代码的可靠性和安全性。如果直接把字段设为public,任何代码都能改动它,可能导致bug。

  • 控制可见性:有时候你只想让字段在编辑器中可见,但在代码中仍然保持私有。比如,你希望设计师在Unity中调整玩家的血量,但不希望脚本的其他部分直接修改它。[SerializeField]就完美解决了这个问题:编辑器可见,代码不可见。

所以,[SerializeField]提供了一种折中方案:既保持了字段的私有性(代码中无法直接访问),又让它在特定场景(如Unity编辑器)中“暴露”出来。

4.序列化的原理

序列化的原理听起来可能复杂,但其实很简单。想象你有一个笔记本,里面记下了游戏中所有对象的状态,比如“玩家血量是100,名字是Hero,位置在(1,2,3)”。当你保存游戏时,程序会把这些信息“翻译”成一种可以存储在硬盘上的格式,比如JSON、XML或二进制数据。这个过程就叫序列化。

反过来,当你加载游戏时,程序会读取硬盘上的这些数据,并把它们“翻译”回程序能理解的对象。这个过程叫反序列化。

在C#和Unity中,[SerializeField]告诉序列化系统:“这个字段很重要,请在序列化和反序列化时包含它。” 如果没有这个标记,系统会忽略掉那些私有的或未标记的字段。

5. 更进一步:与public和private的区别

  • public字段:直接暴露给所有代码和编辑器。优点是简单,缺点是缺乏控制,任何代码都能修改它。

  • private字段(无[SerializeField]):完全隐藏,编辑器看不到,代码也无法直接访问。适合不需要在编辑器中调整的内部数据。

  • private字段 + [SerializeField]:只对编辑器“可见”,代码仍然无法直接访问。适合需要设计师调整但不想让代码乱改的字段。

6 小结:第一性原理的核心

从第一性原理来看,[SerializeField]存在的根本原因是:

  • 需求:我们需要某些数据既能被编辑器看到和修改,又能保持代码的封装性。

  • 问题:默认情况下,私有的字段是隐藏的,公有的字段太开放。

  • 解决方案:[SerializeField]提供了一种折中,让字段在特定场景(比如Unity编辑器)中“暴露”,但在代码中仍然是私密的。

通俗来说,[SerializeField]就像是给字段贴了个标签,告诉系统:“这个字段很重要,请特别对待它!”