深入解析:Unity开发——日拱一卒第一次小结:单例、结构体、字典Demo
结合前面的内容,可以在unity中设计一个项目,把单例模式、结构体、字典的相关内容整合进去。具体思路:在项目的一个脚本中自定义一个公开结构体;然后构建两个场景,在第一个场景中创建一个跨场景不销毁的单例,同时完成字典的声明和初始化,并把字典的值定义为结构体;把第二个场景中字典需要用到的方法都放到单例的脚本里,从而在第二个场景的控制脚本中实现调用。下面是项目结构、脚本代码:
一、准备
1.在Unity中新建2个场景,一个命名为InstanceScene,一个命名为DictionaryScene;在Instance中新建一个空物体,命名为InstanceDemo;另一个场景中新建一个空物体命名为DictionaryDemo,然后新建两个C#脚本,分别命名为InstanceDemo和DictionaryDemo,并分别挂载到两个场景的对应物体上。添加需要的中文字体,具体可以参考:在unity2022(LTS)中添加中文字库的方法
2.在InstanceScene场景和DictionaryScene场景中添加UI控件,如下所示:


二、单例模式
1.首先实现单例模式,在InstanceDemo脚本中写下以下代码,完成单例模式的声明和初始化:
public class InstanceDemo : MonoBehaviour
{
public static InstanceDemo Instance;
private void Awake()
{
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
}
2.在InstanceDemo脚本中添加一些公开的方法,对应字典的增、删、改、查、清零、获取长度、遍历等功能,使得其他脚本文件可以调用:
///
/// 获取字典长度
///
public string InstanceGetDictionaryCount()
{
int count = AllPlayerData.Count;
return count.ToString();
}
///
/// 清空字典
///
public void InstanceClearDictionary()
{
AllPlayerData.Clear();
}
///
/// 删除字典中的指定元素
///
public bool InstanceRemoveCell(ulong playerId)
{
bool isRomove=AllPlayerData.Remove(playerId);
return isRomove;
}
///
/// 获取字典中指定键的值
///
public bool InstanceGetValue(ulong playerId, out PlayerData result)
{
bool isGetValue = AllPlayerData.TryGetValue(playerId, out result);
return isGetValue;
}
///
/// 增加元素
///
public bool InstanceAddCell(ulong playerId, string playerName, int playerLevel)
{
bool isAdded = AllPlayerData.TryAdd(playerId, new PlayerData { playerId = playerId, playerName = playerName, level = playerLevel });
return isAdded;
}
///
/// 修改指定键的值
///
public bool InstanceChangeCell(ulong playerId,string playerName,int playerLevel)
{
if (AllPlayerData.ContainsKey(playerId))
{
AllPlayerData[playerId] = new PlayerData { playerId = playerId, playerName =playerName, level = playerLevel };
return true;
}
else
{
return false;
}
}
///
/// 遍历字典
///
public string InstanceForeachDictionary()
{
string allPlayersInfo = "";
string result;
foreach (KeyValuePair pair in AllPlayerData)
{
ulong key = pair.Key;
PlayerData playerData = pair.Value;
allPlayersInfo += $"ID:{playerData.playerId}\nName:{playerData.playerName}\nLevel:{playerData.level}\n";
}
result = allPlayersInfo;
return result;
}
三、结构体
在项目中新建一个C#脚本,命名为PlayerData,然后写入以下代码:
// 结构体:存储玩家核心数据
public struct PlayerData
{
public ulong playerId; // 玩家唯一ID
public string playerName; // 玩家名称
public int level; // 等级
// 构造方法:初始化结构体
public PlayerData(ulong id, string name, int lv)
{
playerId = id;
playerName = name;
level = lv;
}
//方法:返回playerId
public ulong ReturnPlayerID()
{
return playerId;
}
}
四、字典
1.在InstanceDemo脚本中声明并初始化字典
public class InstanceDemo : MonoBehaviour
{
public static InstanceDemo Instance;
public Button _enterDemoSceneBtn;
public Dictionary AllPlayerData = new Dictionary() {
{ 0, new PlayerData { playerId = 0, playerName = "玩家1", level = 10 } },
{ 1, new PlayerData { playerId = 1, playerName = "玩家2", level = 15 } },
{ 2, new PlayerData { playerId = 2, playerName = "玩家3", level = 20 } }
};
}
2.在DictionaryDemo脚本中调用InstanceDemo单例中公开的方法,实现字典的增、删、改、查、清零、获取长度、遍历等功能,DictionaryDemo脚本的完整代码如下:
using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class DictionaryDemo : MonoBehaviour
{
[Header("翻页")]
public Transform _canvas1;
public Transform _canvas2;
public Button _nextButton;
public Button _preButton;
[Header("获取字典长度")]
public TMP_Text _countTxt;
public Button _getCountBtn;
[Header("字典清零")]
public Button _clearBtn;
[Header("删除字典元素")]
public TMP_InputField _removeInput;
public Button _removeBtn;
public TMP_Text _removeResultTxt;
[Header("访问元素")]
public TMP_InputField _keyInput;
public Button _getValueBtn;
public TMP_Text _valueTxt;
[Header("添加元素")]
public TMP_InputField _keyAddInputField;
public TMP_InputField _nameAddInputField;
public TMP_InputField _levelAddInputField;
public Button _addCellBtn;
public TMP_Text _resultAddTxt;
[Header("修改元素值")]
public TMP_InputField _keyChangeInputField;
public TMP_InputField _nameChangeInputField;
public TMP_InputField _levelChangeInputField;
public Button _changeCellBtn;
public TMP_Text _resultChangeTxt;
[Header("遍历字典")]
public Button _foreachBtn;
public TMP_Text _resultForeachTxt;
private void Start()
{
_canvas1.gameObject.SetActive(true);
_canvas2.gameObject.SetActive(false);
_nextButton.onClick.AddListener(NextPage);
_preButton.onClick.AddListener(PrePage);
_getCountBtn.onClick.AddListener(GetDictionaryCount);
_clearBtn.onClick.AddListener(ClearDictionary);
_removeBtn.onClick.AddListener(RemoveCell);
_getValueBtn.onClick.AddListener(GetDictionaryValue);
_addCellBtn.onClick.AddListener(AddCell);
_changeCellBtn.onClick.AddListener(ChangeCell);
_foreachBtn.onClick.AddListener(ForeachDictionary);
}
private void PrePage()
{
_canvas1.gameObject.SetActive(true);
_canvas2.gameObject.SetActive(false);
}
private void NextPage()
{
_canvas1.gameObject.SetActive(false);
_canvas2.gameObject.SetActive(true);
}
///
/// 获取字典长度,调用单例里的InstanceGetDictionaryCount()方法
///
private void GetDictionaryCount()
{
string count = InstanceDemo.Instance.InstanceGetDictionaryCount();
_countTxt.text = count;
}
///
/// 清空字典,调用单例里的InstanceClearDictionary()方法
///
private void ClearDictionary()
{
InstanceDemo.Instance.InstanceClearDictionary();
}
///
/// 删除字典中的指定元素,调用单例中的InstanceRemoveCell()方法
///
private void RemoveCell()
{
ulong playerId = ulong.Parse(_removeInput.text);
if (InstanceDemo.Instance.InstanceRemoveCell(playerId))
{
_removeResultTxt.text = "键" + _removeInput.text + "的元素被删除!";
}
else
{
_removeResultTxt.text = "键" + _removeInput.text + "的元素删除失败!";
}
}
///
/// 获取字典中指定键的值,调用单例中的InstanceGetValue()方法
///
private void GetDictionaryValue()
{
ulong playerId = ulong.Parse(_keyInput.text);
PlayerData playerData;
bool isGetValue = InstanceDemo.Instance.InstanceGetValue(playerId, out playerData);
if (isGetValue)
{
_valueTxt.text = $"ID:{playerData.playerId}\nName:{playerData.playerName}\nLevel:{playerData.level}";
}
else
{
_valueTxt.text = "键" + _keyInput.text + "不存在!";
}
}
///
/// 增加元素,调用单例中的InstanceAddCell()方法
///
private void AddCell()
{
ulong playerId = ulong.Parse(_keyAddInputField.text);
string playerName = _nameAddInputField.text;
int playerLevel = int.Parse(_levelAddInputField.text);
bool isAdded = InstanceDemo.Instance.InstanceAddCell(playerId, playerName, playerLevel);
if (isAdded)
{
_resultAddTxt.text = "新玩家添加成功!";
}
else
{
_resultAddTxt.text = $"添加失败:{_keyAddInputField.text}键已存在";
}
}
///
/// 修改指定键的值,调用单例中的InstanceChangeCell()方法
///
private void ChangeCell()
{
ulong playerId = ulong.Parse(_keyChangeInputField.text);
string playerName = _nameChangeInputField.text;
int playerLevel = int.Parse(_levelChangeInputField.text);
bool isChange = InstanceDemo.Instance.InstanceChangeCell(playerId, playerName, playerLevel);
if (isChange)
{
_resultChangeTxt.text = $"修改键{playerId}的值成功!";
}
else
{
_resultChangeTxt.text = $"键{playerId}不存在!";
}
}
///
/// 遍历字典,调用单例中的InstanceForeachDictionary()方法
///
private void ForeachDictionary()
{
string result = InstanceDemo.Instance.InstanceForeachDictionary();
_resultForeachTxt.text = result;
}
}
InstanceDemo的完整代码如下:
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class InstanceDemo : MonoBehaviour
{
public static InstanceDemo Instance;
public Button _enterDemoSceneBtn;
public Dictionary AllPlayerData = new Dictionary() {
{ 0, new PlayerData { playerId = 0, playerName = "玩家1", level = 10 } },
{ 1, new PlayerData { playerId = 1, playerName = "玩家2", level = 15 } },
{ 2, new PlayerData { playerId = 2, playerName = "玩家3", level = 20 } }
};
private void Awake()
{
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
private void Start()
{
_enterDemoSceneBtn.onClick.AddListener(EnterDemoScene);
}
private void EnterDemoScene()
{
SceneManager.LoadScene(1);
}
///
/// 获取字典长度
///
public string InstanceGetDictionaryCount()
{
int count = AllPlayerData.Count;
return count.ToString();
}
///
/// 清空字典
///
public void InstanceClearDictionary()
{
AllPlayerData.Clear();
}
///
/// 删除字典中的指定元素
///
public bool InstanceRemoveCell(ulong playerId)
{
bool isRomove=AllPlayerData.Remove(playerId);
return isRomove;
}
///
/// 获取字典中指定键的值
///
public bool InstanceGetValue(ulong playerId, out PlayerData result)
{
bool isGetValue = AllPlayerData.TryGetValue(playerId, out result);
return isGetValue;
}
///
/// 增加元素
///
public bool InstanceAddCell(ulong playerId, string playerName, int playerLevel)
{
bool isAdded = AllPlayerData.TryAdd(playerId, new PlayerData { playerId = playerId, playerName = playerName, level = playerLevel });
return isAdded;
}
///
/// 修改指定键的值
///
public bool InstanceChangeCell(ulong playerId,string playerName,int playerLevel)
{
if (AllPlayerData.ContainsKey(playerId))
{
AllPlayerData[playerId] = new PlayerData { playerId = playerId, playerName =playerName, level = playerLevel };
return true;
}
else
{
return false;
}
}
///
/// 遍历字典
///
public string InstanceForeachDictionary()
{
string allPlayersInfo = "";
string result;
foreach (KeyValuePair pair in AllPlayerData)
{
ulong key = pair.Key;
PlayerData playerData = pair.Value;
allPlayersInfo += $"ID:{playerData.playerId}\nName:{playerData.playerName}\nLevel:{playerData.level}\n";
}
result = allPlayersInfo;
return result;
}
}
3.在unity中,把InstanceScene场景中的UI控件和DictionaryScene场景中的UI控件分别拖拽到InstanceDemo和DictionaryDemo脚本组件对应的位置


五、验证
在unity中,打开InstanceScene场景,然后运行项目,点击进入演示场景,如果各项功能都能正常使用,那么就说明单例、结构体、字典功能都实现了



浙公网安备 33010602011771号