前言
本节主要实现数据的存储和渲染功能
存储
参考:【unity小技巧】Unity存储存档保存——PlayerPrefs、JsonUtility和MySQL数据库的使用
新增DataManager存储脚本
using System.IO; using UnityEngine; using System.Collections.Generic; using Newtonsoft.Json; public class DataManager { public static GameData gameData = new GameData(); public static string savePath = Path.Combine(Application.persistentDataPath, "saveData.json"); // 加密:选择一些用于亦或操作的字符(注意保密) public static char[] keyChars = { 'a', 'b', 'c', 'd', 'e' }; // 加密方法 public static string Encrypt(string data) { char[] dataChars = data.ToCharArray(); for (int i = 0; i < dataChars.Length; i++) { char dataChar = dataChars[i]; char keyChar = keyChars[i % keyChars.Length]; // 重点: 通过亦或得到新的字符 char newChar = (char)(dataChar ^ keyChar); dataChars[i] = newChar; } return new string(dataChars); } // 解密方法 public static string Decrypt(string data) { return Encrypt(data); } //加载用户数据 public static GameData Load() { Debug.Log(savePath); // 检查用户配置文件是否存在 if (File.Exists(savePath)) { // 从文本文件中加载JSON字符串 string jsonData = File.ReadAllText(savePath); // #if UNITY_EDITOR // // 加密5 // jsonData = Decrypt(jsonData); // #endif // 将JSON字符串转换为用户内存数据 gameData = JsonConvert.DeserializeObject<GameData>(jsonData); Debug.Log("加载成功"); return gameData; } else { Debug.Log("无数据"); return null; } } // 保存用户数据 public static void SaveUserData(UserData userData) { gameData.usersData[userData.name] = userData; // 转换用户数据为JSON字符串 // string jsonData = JsonUtility.ToJson(gameData); string jsonData = JsonConvert.SerializeObject(gameData); // #if UNITY_EDITOR // // 加密4 // jsonData = Encrypt(jsonData); // #endif File.WriteAllText(savePath, jsonData); UserEvents.UserList(); Debug.Log("保存成功"); } // 读取用户数据 public static UserData LoadUserData(string userName) { // 率先从缓存中取数据,而不是从文本文件中读取 if (gameData.usersData.ContainsKey(userName)) { return gameData.usersData[userName]; } Load(); return gameData.usersData[userName]; ; } //删除用户 public static bool ClearUserData(string userName) { if (gameData.usersData.ContainsKey(userName)) { gameData.usersData.Remove(userName); }else{ Load(); gameData.usersData.Remove(userName); } string jsonData = JsonConvert.SerializeObject(gameData); // #if UNITY_EDITOR // // 加密4 // jsonData = Encrypt(jsonData); // #endif File.WriteAllText(savePath, jsonData); // 触发事件 UserEvents.UserList(); return true; } // 保存当前用户 public static void SaveClientData(ClientData data) { gameData.clientData = data; // 转换用户数据为JSON字符串 string jsonData = JsonConvert.SerializeObject(gameData); // #if UNITY_EDITOR // // 加密4 // jsonData = Encrypt(jsonData); // #endif File.WriteAllText(savePath, jsonData); // 触发事件 UserEvents.UserClient(data); } // 读取当前用户 public static ClientData LoadClientData() { if (gameData.clientData != null) { return gameData.clientData; } // 率先从缓存中取数据,而不是从文本文件中读取 Load(); return gameData.clientData; } } public class GameData { public Dictionary<string, UserData> usersData = new Dictionary<string, UserData>(); public ClientData clientData; } public class UserData { public string name; public int level; public UserData(string name, int level) { this.name = name; this.level = level; } } public class ClientData { public string curUserName = ""; public ClientData(string curUserName) { this.curUserName = curUserName; } }
使用案例例子
DataManager.SaveUserData(new UserData(input.text, 1)); DataManager.SaveClientData(new ClientData(input.text));
添加列表数据
新增AddUserPanel ,控制添加数据
public class AddUserPanel : BasePanel { public Button btnOK; public Button btnCancel; public TMP_InputField input; private void Awake() { btnOK.onClick.AddListener(OnBtnOK); btnCancel.onClick.AddListener(OnBtnCancel); } public void OnBtnOK() { DataManager.SaveUserData(new UserData(input.text, 1)); DataManager.SaveClientData(new ClientData(input.text)); ClosePanel(); UIManager.Instance.ClosePanel(UIConst.UserListPanel); } public void OnBtnCancel() { ClosePanel(); } }
配置
效果
查看存储的json数据
渲染用户列表数据,修改UserListPanel
新增UserNameItem,用户容器控制脚本
public class UserNameItem : MonoBehaviour { private GameObject select;//选中 private TextMeshProUGUI txt;//文本 private UserData userData; private Button btn; private UserListPanel parent; private void Awake() { txt = transform.Find("用户").GetComponent<TextMeshProUGUI>(); select = transform.Find("选中").gameObject; select.SetActive(false); btn = GetComponent<Button>(); btn.onClick.AddListener(OnBtnNameItem); } public void Init(UserData userData, UserListPanel userPanel) { this.userData = userData; txt.text = userData.name; parent = userPanel; } void OnBtnNameItem() { parent.CurName = userData.name; } public void RefreSelect() { select.SetActive(userData.name == parent.CurName); } }
新增UserListPanel ,控制用户列表显示
public class UserListPanel : BasePanel { public ScrollRect scroll; public GameObject UserNamePrefab; public Button btnOK; public Button btnCancel; public Button btnAddUser; public Button btnRename; public Button btnRemove; private Dictionary<string, UserNameItem> menuNameItems = new Dictionary<string, UserNameItem>(); private string curUserName; public string CurName { get { return curUserName; } set { curUserName = value; RefreshSelectState(); } } public void RefreshSelectState() { // 刷新所有子节点的选中状态 foreach (UserNameItem item in menuNameItems.Values) { item.RefreSelect(); } } private void Awake() { btnOK.onClick.AddListener(OnBtnOK); btnCancel.onClick.AddListener(OnBtnCancel); btnAddUser.onClick.AddListener(OnBtnAddUser); btnRename.onClick.AddListener(OnBtnRename); btnRemove.onClick.AddListener(OnBtnRemove); } private void OnBtnRename(){ if(CurName == DataManager.LoadClientData().curUserName){ UIManager.Instance.OpenTips("不可修改当前用户"); return; } BasePanel basePanel = UIManager.Instance.OpenPanel(UIConst.EditUserPanel); basePanel.GetComponent<EditUserPanel>().CurName = curUserName; } private void OnBtnRemove(){ if(curUserName == DataManager.LoadClientData().curUserName){ UIManager.Instance.OpenTips("不可删除当前用户"); return; } DataManager.ClearUserData(curUserName); } private void Start() { curUserName = DataManager.LoadClientData().curUserName; RefreshMainPanel(); RefreshSelectState(); } // 注册事件监听器 private void OnEnable() { UserEvents.onUserList += ChangeUserList; } // 注销事件监听器 private void OnDisable() { UserEvents.onUserList -= ChangeUserList; } private void ChangeUserList() { RefreshMainPanel(); } //刷新列表 public void RefreshMainPanel() { menuNameItems.Clear(); //删除原来数据 foreach (Transform child in scroll.content) { Destroy(child.gameObject); } Dictionary<string, UserData> usersData = DataManager.Load().usersData; foreach (string type in usersData.Keys) { UserData userData = usersData[type]; Transform prefab = Instantiate(UserNamePrefab).transform; prefab.SetParent(scroll.content, false); prefab.GetComponent<UserNameItem>().Init(userData, this); menuNameItems.Add(userData.name, prefab.GetComponent<UserNameItem>()); } } public void OnBtnOK() { DataManager.SaveClientData(new ClientData(curUserName)); ClosePanel(); } public void OnBtnCancel() { ClosePanel(); } public void OnBtnAddUser() { UIManager.Instance.OpenPanel(UIConst.AddUserPanel); } }
配置
引入事件,实现界面变化
具体可以参考:【unity实战】事件(Event)的基本实战使用
新增UserEvents
public class UserEvents { public static event Action<ClientData> onClient; public static event Action onUserList; public static void UserClient(ClientData clientData) { onClient?.Invoke(clientData); } public static void UserList() { onUserList?.Invoke(); } }
在数据变化时调用,触发事件
UserEvents.UserList(); UserEvents.UserClient(data);
在注册事件,比如用户列表面板UserListPanel
// 注册事件监听器 private void OnEnable() { UserEvents.onUserList += ChangeUserList; } // 注销事件监听器 private void OnDisable() { UserEvents.onUserList -= ChangeUserList; } private void ChangeUserList() { RefreshMainPanel(); }
效果
完结
其中还有一些细节这里就不多说了,自己按照喜欢去配置即可