深入解析: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场景,然后运行项目,点击进入演示场景,如果各项功能都能正常使用,那么就说明单例、结构体、字典功能都实现了

posted @ 2025-11-09 17:54  clnchanpin  阅读(38)  评论(0)    收藏  举报