问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Unity 基础——脚本管理与序列化详解:从入门到高级

创作时间:
作者:
@小白创作中心

Unity 基础——脚本管理与序列化详解:从入门到高级

引用
CSDN
1.
https://blog.csdn.net/MY_future_/article/details/145935183

在Unity开发中,脚本管理和序列化是两个非常重要的概念。脚本管理涉及如何组织、加载和运行脚本,而序列化则是Unity将对象状态保存和加载的核心机制。本文将基于《Unity3D游戏开发》(宣雨松 第3版)的内容,结合Unity的最新特性,详细解析脚本管理和序列化的相关知识,帮助你编写更高效、更可维护的Unity项目。

一.脚本管理

1. 脚本的组织与加载

在Unity中,脚本通常以C#类的形式存在,并附加到GameObject上。以下是一些脚本管理的最佳实践:

  • 模块化设计:将功能拆分为独立的脚本,例如PlayerController、EnemyAI等。
  • 命名空间:使用命名空间避免命名冲突,例如:
namespace Game.Player {
    public class PlayerController : MonoBehaviour { ... }
}
  • 动态加载脚本:通过Resources.Load或Addressables动态加载脚本。
MonoBehaviour script = gameObject.AddComponent<MyScript>();

2. 脚本的执行顺序

Unity允许开发者自定义脚本的执行顺序,以确保某些脚本在其他脚本之前运行。

  • 设置执行顺序

  • 在Unity编辑器中,选择Edit → Project Settings → Script Execution Order

  • 添加脚本并调整其执行顺序。

  • 代码控制执行顺序

  • 使用[DefaultExecutionOrder]属性设置脚本的执行顺序。

[DefaultExecutionOrder(-100)]
public class EarlyScript : MonoBehaviour { ... }

3. 脚本的启用与禁用

通过enabled属性可以控制脚本的启用与禁用。

public class MyScript : MonoBehaviour {
    void Start() {
        enabled = false; // 禁用脚本
    }
    void Update() {
        if (Input.GetKeyDown(KeyCode.Space)) {
            enabled = true; // 启用脚本
        }
    }
}

二.序列化

1. 序列化的概念

序列化是将对象的状态转换为可存储或传输的格式的过程。Unity使用序列化来保存场景、预制体和脚本数据。

  • 序列化的作用

  • 保存场景和预制体的状态。

  • 在编辑器和运行时之间传递数据。

  • 序列化的类型

  • 隐式序列化:Unity自动序列化公共字段和标记为[SerializeField]的私有字段。

  • 显式序列化:通过实现ISerializationCallbackReceiver接口自定义序列化逻辑。

2. Unity的序列化机制

  • 可序列化的字段

  • 公共字段:默认会被序列化。

    public int health = 100;
    
  • 私有字段:需要添加[SerializeField]属性。

    [SerializeField] private int ammo = 10;
    
  • 不可序列化的字段

  • 静态字段:不会被序列化。

  • 标记为[NonSerialized]的字段:显式禁止序列化。

    [NonSerialized] public int tempValue;
    

3. 自定义序列化

通过实现ISerializationCallbackReceiver接口,可以自定义序列化和反序列化的逻辑。

using UnityEngine;
public class CustomSerialization : MonoBehaviour, ISerializationCallbackReceiver {
    public int health;
    [SerializeField] private int serializedHealth;
    public void OnBeforeSerialize() {
        serializedHealth = health; // 序列化前保存数据
    }
    public void OnAfterDeserialize() {
        health = serializedHealth; // 反序列化后加载数据
    }
}

4. ScriptableObject的序列化

ScriptableObject是Unity中用于存储数据的特殊对象,支持序列化。

  • 创建ScriptableObject

    using UnityEngine;
    [CreateAssetMenu(fileName = "NewData", menuName = "Game/Data")]
    public class GameData : ScriptableObject {
        public int score;
        public string playerName;
    }
    
  • 使用ScriptableObject

    public class GameManager : MonoBehaviour {
        public GameData gameData;
        void Start() {
            Debug.Log($"Player: {gameData.playerName}, Score: {gameData.score}");
        }
    }
    

三.实际应用案例

案例1:动态加载脚本

public class ScriptLoader : MonoBehaviour {
    void Start() {
        // 动态加载脚本并附加到GameObject
![](https://wy-static.wenxiaobai.com/chat-rag-image/13594619909694218245)
        MonoBehaviour script = gameObject.AddComponent<MyScript>();
    }
}

案例2:自定义序列化

using UnityEngine;
public class PlayerData : MonoBehaviour, ISerializationCallbackReceiver {
    public int health;
    [SerializeField] private int serializedHealth;
    public void OnBeforeSerialize() {
        serializedHealth = health;
    }
    public void OnAfterDeserialize() {
        health = serializedHealth;
    }
}

案例3:使用ScriptableObject存储游戏数据

using UnityEngine;
[CreateAssetMenu(fileName = "NewLevelData", menuName = "Game/LevelData")]
public class LevelData : ScriptableObject {
    public string levelName;
    public int difficulty;
}
public class LevelManager : MonoBehaviour {
    public LevelData levelData;
    void Start() {
        Debug.Log($"Level: {levelData.levelName}, Difficulty: {levelData.difficulty}");
    }
}

总结

脚本管理和序列化是Unity开发中的核心概念。通过合理组织脚本、控制执行顺序以及掌握序列化机制,你可以编写出高效、可维护的游戏项目。希望本文能帮助你更好地理解这些知识,并在实际开发中灵活运用。


© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号