Unity 数据持久化 之 完全搞定ScriptableObject
2025/5/8重置
·
目录
1.什么是ScriptableObject
如题,一个可以在Unity编辑器中方便编辑数据的工具
其概述
在unity之中如何操作:
一个让需要的类去继承该类,并且序列化或者有公共变量,即可在Inspector窗口看到它们
2.创建一个ScriptableObject类
先让需要的类去继承ScriptableObject
使用CreateAssetMenu创建一个ScriptableObjec配置文件
[CreateAssetMenu(fileName ="文件名" ,menuName ="菜单名",order =0)]
当我的脚本中写了如下变量之后:
public int a;
public string b;
[SerializeField]
private GameObject c;
该文件就会出现对应的变量
3.CreateInstance简单使用
首先,我有一个继承ScriptableObject的脚本,里面有三个变量和一个打印方法
[CreateAssetMenu(fileName ="文件名" ,menuName ="菜单名",order =0)]
public class LearnScripttableObject : ScriptableObject
{
public int a;
public string b;
[SerializeField]
private GameObject c;
public void printinfo()
{
Debug.Log(a);
Debug.Log(b);
Debug.Log(c);
}
}
之后可以到其他脚本之中进行创建并修改
private void Awake()
{
dates = ScriptableObject.CreateInstance<LearnScripttableObject>();
dates.a = 10;
dates.b = "任意字符串";
dates.printinfo();
}
4.So转JSON存取
Unity数据持久化 之 Json序列化与反序列化_unity json 反序列化-CSDN博客
Unity数据持久化 之 LitJson序列化与反序列化_unity litjson-CSDN博客
这里以Utility作演示
public class ScritableObjectPersistence :MonoBehaviour
{
LearnScripttableObject dates;
private void Awake()
{
dates = ScriptableObject.CreateInstance<LearnScripttableObject>();
dates.a = 10;
dates.b = "任意字符串";
dates.printinfo();
string str =JsonUtility.ToJson(dates);
File.WriteAllText(Application.persistentDataPath+"text.json",str);
print(Application.persistentDataPath);
}
}
取(override原有的数据)
string newstr = File.ReadAllText(Application.persistentDataPath + "text.json");
JsonUtility.FromJsonOverwrite(newstr, dates);
5.通过Excel配置So文件
下面是我写的一个做本地化的脚本 可以不用关心其内部逻辑
想要做的是 将下面这个表格读取到So文件之中
如果你发现和你的编辑器不太一样 是因为我使用了Odin插件
之后一键导表
补充编辑器拓展代码:
using System;
using System.Collections.Generic;
using System.IO;
using OfficeOpenXml;
using UnityEditor;
using UnityEngine;
using UnityEngine.Video;
namespace MieMieFrameTools
{
public class ExcelLocalizationImporterEditor : EditorWindow
{
private LocalizationSetting localizationSettingInstance;
private string excelFilePath;
private string dragDropFeedback = "拖放 Excel 文件到此区域";
private GUIStyle normalStyle;
private GUIStyle draggedStyle;
[MenuItem("MieMieFrameTools/Excel/本地化Excel导入工具")]
static void OpenWindow()
{
GetWindow<ExcelLocalizationImporterEditor>("本地化Excel导入工具");
}
void OnEnable()
{
normalStyle = new GUIStyle
{
alignment = TextAnchor.MiddleCenter,
normal = new GUIStyleState { background = EditorGUIUtility.whiteTexture },
border = new RectOffset(2, 2, 2, 2),
padding = new RectOffset(10, 10, 10, 10)
};
normalStyle.normal.textColor = Color.grey;
var grayTex = new Texture2D(1, 1);
grayTex.SetPixel(0, 0, new Color(0.85f, 0.85f, 0.85f));
grayTex.Apply();
draggedStyle = new GUIStyle(normalStyle)
{
normal = new GUIStyleState { background = grayTex, textColor = Color.black }
};
}
void OnGUI()
{
GUILayout.Label("本地化Excel导入工具", EditorStyles.boldLabel);
GUILayout.Space(10);
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
GUILayout.Label("LocalizationSetting 实例", EditorStyles.boldLabel);
localizationSettingInstance = (LocalizationSetting)EditorGUILayout.ObjectField(
localizationSettingInstance, typeof(LocalizationSetting), false);
EditorGUILayout.EndVertical();
GUILayout.Space(10);
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
GUILayout.Label("Excel 文件导入", EditorStyles.boldLabel);
Rect dropArea = GUILayoutUtility.GetRect(0f, 60f, GUILayout.ExpandWidth(true));
if (string.IsNullOrEmpty(excelFilePath))
{
GUI.Box(dropArea, dragDropFeedback, normalStyle);
}
else
{
GUI.Box(dropArea, Path.GetFileName(excelFilePath), draggedStyle);
}
HandleDragAndDrop(dropArea);
EditorGUILayout.EndVertical();
GUILayout.Space(10);
if (GUILayout.Button("执行导入", GUILayout.Height(30)))
{
if (localizationSettingInstance == null)
{
EditorUtility.DisplayDialog("错误", "请先选择 LocalizationSetting 实例", "确定");
return;
}
if (string.IsNullOrEmpty(excelFilePath))
{
EditorUtility.DisplayDialog("错误", "请先拖放 Excel 文件", "确定");
return;
}
ImportLocalizationFromExcel(excelFilePath, localizationSettingInstance);
EditorUtility.SetDirty(localizationSettingInstance);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
EditorUtility.DisplayDialog("成功", "导入完成", "确定");
}
}
void HandleDragAndDrop(Rect area)
{
Event currentEvent = Event.current;
switch (currentEvent.type)
{
case EventType.DragUpdated:
case EventType.DragPerform:
if (area.Contains(currentEvent.mousePosition))
{
DragAndDrop.visualMode = DragAndDropVisualMode.Generic;
if (currentEvent.type == EventType.DragPerform)
{
DragAndDrop.AcceptDrag();
foreach (string draggedPath in DragAndDrop.paths)
{
if (draggedPath.EndsWith(".xlsx"))
{
excelFilePath = draggedPath;
Repaint();
}
else
{
EditorUtility.DisplayDialog("错误", "仅支持 .xlsx 文件", "确定");
}
}
}
}
break;
case EventType.DragExited:
if (string.IsNullOrEmpty(excelFilePath))
{
dragDropFeedback = "拖放 Excel 文件到此区域";
Repaint();
}
break;
}
}
static void ImportLocalizationFromExcel(string filePath, LocalizationSetting localizationSetting)
{
localizationSetting.dataBag = new Dictionary<string, LocalizationTypeAllData>();
FileInfo file = new FileInfo(filePath);
using (ExcelPackage package = new ExcelPackage(file))
{
ExcelWorksheet worksheet = package.Workbook.Worksheets[1];
// 动态获取列索引
int resourceTypeCol = -1;
int resourcePathCol = -1;
List<int> languageColumns = new List<int>();
List<E_LanuageType> languageTypes = new List<E_LanuageType>();
for (int col = 1; col <= worksheet.Dimension.End.Column; col++)
{
string colName = worksheet.Cells[1, col].Value?.ToString()?.Trim();
if (Enum.TryParse<E_LanuageType>(colName, true, out var languageType))
{
languageColumns.Add(col);
languageTypes.Add(languageType);
}
else if (colName == "资源类型")
{
resourceTypeCol = col;
}
else if (colName == "资源路径")
{
resourcePathCol = col;
}
}
if (resourceTypeCol == -1 || resourcePathCol == -1 || languageColumns.Count == 0)
{
Debug.LogError("Excel 列结构不正确,缺少必要列");
return;
}
int rowCount = worksheet.Dimension.End.Row;
for (int row = 2; row <= rowCount; row++)
{
var typeName = worksheet.Cells[row, 1].Value?.ToString()?.Trim();
var contentKey = worksheet.Cells[row, 2].Value?.ToString()?.Trim();
var resourceType = worksheet.Cells[row, resourceTypeCol].Value?.ToString()?.Trim();
var resourcePath = worksheet.Cells[row, resourcePathCol].Value?.ToString()?.Trim();
if (string.IsNullOrEmpty(typeName) || string.IsNullOrEmpty(contentKey))
{
continue;
}
if (!localizationSetting.dataBag.ContainsKey(typeName))
{
localizationSetting.dataBag[typeName] = new LocalizationTypeAllData();
}
LocalizationTypeAllData typeAllData = localizationSetting.dataBag[typeName];
LocalizationModel model = null;
foreach (var m in typeAllData.GetIModelList())
{
if (m.contentKey == contentKey)
{
model = m;
break;
}
}
if (model == null)
{
model = new LocalizationModel(contentKey);
typeAllData.GetIModelList().Add(model);
}
for (int i = 0; i < languageColumns.Count; i++)
{
var languageType = languageTypes[i];
var content = worksheet.Cells[row, languageColumns[i]].Value?.ToString()?.Trim();
L_Object lObject = null;
switch (resourceType.ToLower())
{
case "文本":
if (string.IsNullOrEmpty(content))
{
continue; // 文本内容为空则跳过
}
lObject = new L_Text { content = content };
break;
case "图片":
if (string.IsNullOrEmpty(resourcePath) || resourcePath.ToLower().Equals("null"))
{
continue; // 图片资源路径为 null 则跳过
}
lObject = new L_Image { content = UnityEngine.Resources.Load<Sprite>(resourcePath) };
break;
case "音频":
if (string.IsNullOrEmpty(resourcePath) || resourcePath.ToLower().Equals("null"))
{
continue; // 音频资源路径为 null 则跳过
}
lObject = new L_Audio { content = UnityEngine.Resources.Load<AudioClip>(resourcePath) };
break;
case "视频":
if (string.IsNullOrEmpty(resourcePath) || resourcePath.ToLower().Equals("null"))
{
continue; // 视频资源路径为 null 则跳过
}
lObject = new L_Video { content = UnityEngine.Resources.Load<VideoClip>(resourcePath) };
break;
case "textmeshpro":
if (string.IsNullOrEmpty(content))
{
continue; // 文本内容为空则跳过
}
lObject = new L_Tmp { content = content };
break;
case "精灵图":
if (string.IsNullOrEmpty(resourcePath) || resourcePath.ToLower().Equals("null"))
{
continue; // 精灵图资源路径为 null 则跳过
}
lObject = new L_Sprite { content = UnityEngine.Resources.Load<Sprite>(resourcePath) };
break;
default:
continue;
}
if (lObject != null)
{
model.lanuageModeDict[languageType] = lObject;
}
}
}
}
}
}
}

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐
所有评论(0)