Unity 資料(Data) 與 序列化(Serialization)
資料結構
在 Unity 中儲存資料時要選擇適合的資料結構來儲存,以下是 C# 常用的資料結構。
- 陣列 (Array):陣列適用於大小固定、元素類型一致的集合。例如,儲存固定數量的關卡分數或完成狀態。
1
2
3int[] levelScores = new int[10]; // 用於存儲 10 個關卡的分數
levelScores[0] = 100; // 第一關的分數
levelScores[1] = 200; // 第二關的分數 - 列表 (List):列表是動態的,能在執行時調整大小,適合在需要新增或移除元素的情境。例如,動態管理角色的物品欄。
1
2
3List<string> inventoryItems = new List<string>(); // 用於儲存物品清單
inventoryItems.Add("Item1"); // 添加物品
inventoryItems.Add("Item2"); // 添加物品 - 字典 (Dictionary):字典是鍵(Key)與值(Value)的儲存方式,適合需要快速查找的情況。例如,排行榜系統或配置表。
1
2
3Dictionary<string, int> leaderboard = new Dictionary<string, int>(); // 玩家名稱對應分數
leaderboard["Player1"] = 1000; // Player1 的分數
leaderboard["Player2"] = 1500; // Player2 的分數 - 自定義資料結構:當內建資料結構無法滿足需求時,可設計自定義結構以應對特定場景。例如,設計角色屬性與技能系統。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20public class Character
{
public string Name;
public int Health;
public int Mana;
public List<string> Abilities;
public Character(string name, int health, int mana)
{
Name = name;
Health = health;
Mana = mana;
Abilities = new List<string>();
}
public void AddAbility(string ability)
{
Abilities.Add(ability);
}
}
資料結構對效能的影響
- 優化記憶體使用
選用適當的資料結構能減少不必要的記憶體浪費。例如:若需要儲存固定數量的元素,可使用 陣列 (Array) 而非列表 (List)。陣列因固定大小而佔用較少的記憶體空間。 - 提升存取與檢索速度
不同的資料結構提供不同的存取效率,選擇合適的結構能顯著提升遊戲回應速度。例如:字典 (Dictionary) 提供常數時間的查找,非常適合需要快速檢索的場景,例如排行榜的玩家數據。 - 高效的資料操作
適合的資料結構能簡化資料新增、刪除等操作,讓遊戲流程更順暢。例如:列表 (List) 適合用於需要頻繁增刪元素的場景,例如動態的物品欄。 - 降低處理負擔
選用適當的資料結構可減少額外處理,進一步提升遊戲效能。例如:若需要按順序遍歷元素,使用 列表 (List) 而非字典 (Dictionary) 可避免多餘的鍵值查找。
資料序列化 (Serialization)
序列化是將資料轉換為可儲存或傳輸的格式(如 JSON 或 XML)。在 Unity 中,以下是常見的序列化方法
- 使用 JSON 序列化,適合用於需要與網路服務或跨平台數據交換的情境。而 Unity 內建的 JsonUtility 類別,適合簡單的序列化。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26using UnityEngine;
[ ]
public class GameData
{
public int playerLevel;
public int playerScore;
}
public class SerializationExample : MonoBehaviour
{
private void Start()
{
// 建立資料
GameData data = new GameData { playerLevel = 10, playerScore = 500 };
// 序列化
string json = JsonUtility.ToJson(data);
Debug.Log("Serialized JSON: " + json);
// 反序列化
GameData loadedData = JsonUtility.FromJson<GameData>(json);
Debug.Log("Loaded Level: " + loadedData.playerLevel);
Debug.Log("Loaded Score: " + loadedData.playerScore);
}
} - 使用 XML 序列化,XML (eXtensible Markup Language) 是一種結構化的數據格式,常用於儲存遊戲設定(configuration settings)或是與舊系統的兼容。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32using System.IO;
using System.Xml.Serialization;
using UnityEngine;
[ ]
public class GameData
{
public int playerLevel;
public int playerScore;
}
public class XmlSerializationExample : MonoBehaviour
{
private void Start()
{
// 建立資料
GameData data = new GameData { playerLevel = 10, playerScore = 500 };
// 序列化
XmlSerializer serializer = new XmlSerializer(typeof(GameData));
StringWriter writer = new StringWriter();
serializer.Serialize(writer, data);
string xml = writer.ToString();
Debug.Log("Serialized XML: " + xml);
// 反序列化
StringReader reader = new StringReader(xml);
GameData loadedData = (GameData)serializer.Deserialize(reader);
Debug.Log("Loaded Level: " + loadedData.playerLevel);
Debug.Log("Loaded Score: " + loadedData.playerScore);
}
} - 二進位序列化(Binary serialization)
二進位序列化是一種將物件壓縮成緊湊的二進位格式的方式,適合用於需要高效儲存或讀寫數據的情境,例如保存遊戲進度或本地化配置文件。相比於 JSON 或 XML 等文本格式,二進位格式在讀取和寫入速度上具有顯著優勢,同時生成的數據也更小。
但 BinaryFormatter 在 ASP.NET 應用程式中已淘汰並禁止。 - ScriptableObject
ScriptableObject 是 Unity 中用來存儲資料的資源(assets)類型,提供一種直觀的方式來管理設定、參數和可重複使用的組件。它們在 Unity 編輯器中以序列化的格式儲存數據。- 定義 ScriptableObject
1
2
3
4
5
6
7
8using UnityEngine;
[ ]
public class GameSettings : ScriptableObject
{
public int playerHealth;
public int enemyCount;
public float playerSpeed;
} - ScriptableObject 的序列化與反序列化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31using UnityEngine;
using System.IO;
public class SettingsManager : MonoBehaviour
{
public GameSettings gameSettings; // 引用 ScriptableObject
// 保存遊戲設定到檔案
public void SaveSettings()
{
string jsonSettings = JsonUtility.ToJson(gameSettings); // 序列化為 JSON
File.WriteAllText(Application.persistentDataPath + "/settings.json", jsonSettings); // 寫入檔案
Debug.Log("Settings saved to " + Application.persistentDataPath + "/settings.json");
}
// 從檔案加載遊戲設定
public void LoadSettings()
{
string path = Application.persistentDataPath + "/settings.json";
if (File.Exists(path)) // 檢查檔案是否存在
{
string jsonSettings = File.ReadAllText(path); // 讀取檔案
JsonUtility.FromJsonOverwrite(jsonSettings, gameSettings); // 將 JSON 加載到現有的 ScriptableObject
Debug.Log("Settings loaded from " + path);
}
else
{
Debug.LogWarning("Settings file not found at " + path);
}
}
}
- 定義 ScriptableObject
PlayerPrefs
PlayerPrefs 是 Unity 提供的內建解決方案,用於以鍵(Key)值(Value)對的形式存儲小型資料,如玩家偏好設置、基本遊戲進度或遊戲內設置資料。它易於使用且跨平臺支持,適合管理輕量級資料。
- PlayerPrefs 僅支持基礎類型(如 int、float 和 string),
- 如果需要存儲更複雜的資料結構,則需要進行序列化。將資料轉換為 JSON 或 XML 格式,然後以字符串形式存儲到 PlayerPrefs 中。
- PlayerPrefs 的資料以明文形式存儲,容易受到未授權的訪問。
- 何時不使用 PlayerPrefs,儘管 PlayerPrefs 簡單易用,但在以下情況下可能並不適合:
- 大型資料:對於複雜或大規模資料,就不適合使用,可改使用資料庫(如 SQLite)。
- 敏感數據:對於高度敏感的信息,應考慮使用加密文件或平台特定的安全存儲方案。
- 網絡同步:PlayerPrefs 不適合在設備間同步資料,應使用雲存儲或服務器端資料管理。