0

我有一个单例类,其中包含有关我的游戏的一般信息。

public class GeneralGameData : ScriptableObject
{
    private static GeneralGameData _currentGeneralGameData;

    public static GeneralGameData CurrentGeneralGameData
    {
        get
        {
            if (_currentGeneralGameData == null)
            {
                _currentGeneralGameData = CreateInstance<GeneralGameData>();
            }

            DontDestroyOnLoad(_currentGeneralGameData);

            return _currentGeneralGameData;
        }
    }

    public string GameName;

    public string GameVersion;

}

此类在场景中没有礼物。

我还有一个窗口可以显示和更改它

 public class GeneralGameDataMenuItem : EditorWindow
{
    [MenuItem("CoreMaker/GeneralGameData")]
    private static void _generalGameData()
    {
        GetWindow<GeneralGameDataMenuItem>("GeneralGameData");
    }

    void OnGUI()
    {
        GeneralGameData.CurrentGeneralGameData.GameName = EditorGUILayout.TextField("GameName", GeneralGameData.CurrentGeneralGameData.GameName);
        GeneralGameData.CurrentGeneralGameData.GameVersion = EditorGUILayout.TextField("GameVersion", GeneralGameData.CurrentGeneralGameData.GameVersion);

        EditorUtility.SetDirty(GeneralGameData.CurrentGeneralGameData);
    }
}

问题是在我点击播放或重新启动统一后它不会保存我的更改。有什么解决办法??

4

3 回答 3

0

AScriptableObject旨在保存为资产。[CreateAssetMenu(menuName = "MyGame/GeneralGameData")]在类声明上方添加一行ScriptableObject,然后在项目窗格中右键单击,单击Create > MyGame > GeneralGameData。填写您需要的所有字段。任何需要引用它的脚本都可以添加一个类型的公共字段GeneralGameData并将该资产添加到检查器中。

于 2020-10-11T21:33:27.220 回答
0

这是基于 Nailuj29s 答案的固定代码,但您不需要通过拥有公共字段来引用它,而只需使用GeneralGameData.CurrentGeneralGameData.

公共类 GeneralGameData : ScriptableObject { 私有静态 GeneralGameData _currentGeneralGameData;

    public static GeneralGameData CurrentGeneralGameData
    {
        get
        {
            if (_currentGeneralGameData == null)
            {
                if (AssetDatabase.FindAssets("GeneralGameData", new []{ "Assets/CoreMaker" }).Length != 1)
                {
                    _currentGeneralGameData = CreateInstance<GeneralGameData>();

                    if (!AssetDatabase.IsValidFolder("Assets/CoreMaker"))
                    {
                        AssetDatabase.CreateFolder("Assets", "CoreMaker");
                    }

                    AssetDatabase.CreateAsset(_currentGeneralGameData,"Assets/CoreMaker/GeneralGameData.asset");
                }
            }

            _currentGeneralGameData = AssetDatabase.LoadAssetAtPath<GeneralGameData>("Assets/CoreMaker/GeneralGameData.asset");

            return _currentGeneralGameData;
        }
    }

    public string GameName;
  

    public string GameVersion;
    
}

请记住,当您引用GeneralGameData.CurrentGeneralGameData它时,它将创建和资产,如果您删除该资产,您将丢失数据。

于 2020-10-14T13:36:44.597 回答
0

您丢失数据的原因是因为人们使用 ScriptableObject 的方式有两种。关键区别在于如何设置静态值。(例如_currentGeneralGameData = CreateInstance<GeneralGameData>()代码中的行)

来自资产资源: 这是一个共享的“实际”对象/文件,存在于您的项目资源中。当您更改它时,更改是“永久的”(保存到该实际对象),我相信这就是您正在寻找的。在您的情况下,这意味着只需获取对现有资产资源的引用,而不是创建新实例,类似于:

_currentGeneralGameData = Resources.Load<GeneralGameData>("GeneralGameData");

或者

_currentGeneralGameData = Resources.FindObjectsOfTypeAll<GeneralGameData>().FirstOrDefault();

注意:为了清楚起见,跳过验证/错误处理代码。重要提示:运行时(独立)与编辑器将获得不同的行为:您可能需要在场景中明确引用 ScriptableObject 资源,以确保它没有被优化。更多详情请访问:https ://baraujo.net/unity3d-making-singletons-from-scriptableobjects-automatically/

来自资产的实例: 这是您当前的代码。您无需获取共享资产,而是创建一个 FRESH 实例,与保存在磁盘上的内容断开连接,这意味着您将不会保存您在运行时所做的任何更改。

这非常好,在某些情况下可能更可取,但如果您确实想保留更改,那么您应该使用资产资源方法。

于 2021-09-08T13:38:50.193 回答