创建具有常量唯一 ID 的可编写脚本的对象

Son*_*305 5 c# unity-game-engine

我使用可编写脚本的对象为我的 Unity 游戏创建项目。假设我创建了一根棍子、一把剑和一个头盔。现在要使用它们,我需要将它们拖到一个列表中,在游戏开始时,每个项目都会获得一个分配的 ID,这也是列表中的位置,因为我只需循环遍历列表来分配 ID。现在我可以通过使用它拥有的索引来访问该项目,或者,如大多数关于 ScriptableObjects 的教程所示,然后我们可以将项目和 id 添加到 Dictionary 以更好地访问它们。

Stick 为 0,Sword 为 1,Helmet 为 2。现在我决定用补丁移除剑,因此头盔的 ID 为 1。现在每个存档都被破坏了,因为剑变成了头盔。

我如何处理分配的固定 ID,这些 ID 在我真的想再次分配之前不会改变并且不会被另一个项目占用?我当然可以为我创建的每个 ScriptableObject 对 id 进行硬编码,但正如您想象的那样,管理硬编码的 ID 似乎不是一个好主意。

Blu*_*ssa 10

这是我的看法:

  1. 创建一个自定义属性“ScriptableObjectIdAttribute”,您可以在任何您需要的 id 前面使用它。
  2. 创建一个自定义属性抽屉,以便在您第一次访问检查器中的对象时初始化 id,并使其不可被检查器编辑。
  3. (可选)使用该 Id 属性创建一个基类,并扩展所有需要从中获得唯一 Id 的 ScriptableObject。

BaseScriptableObject.cs:

using System;
using UnityEditor;
using UnityEngine;

public class ScriptableObjectIdAttribute : PropertyAttribute { }

#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(ScriptableObjectIdAttribute))]
public class ScriptableObjectIdDrawer : PropertyDrawer {
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
        GUI.enabled = false;
        if (string.IsNullOrEmpty(property.stringValue)) {
            property.stringValue = Guid.NewGuid().ToString();
        }
        EditorGUI.PropertyField(position, property, label, true);
        GUI.enabled = true;
    }
}
#endif

public class BaseScriptableObject : ScriptableObject {
    [ScriptableObjectId]
    public string Id;
}
Run Code Online (Sandbox Code Playgroud)

武器.cs:

using System;
using UnityEngine;

[CreateAssetMenu(fileName = "weapon", menuName = "Items/Weapon")]
public class Weapon : BaseScriptableObject {
    public int Attack;
    public int Defence;
}
Run Code Online (Sandbox Code Playgroud)

结果 : 在此输入图像描述


小智 6

创建一个字符串“ID”变量,在脚本对象验证时检查它是否为空。如果为空,则创建一个 GUID,如果不是,则不执行任何操作。

public string UID;
        private void OnValidate()
        {
    #if UNITY_EDITOR
            if (UID == "")
            {
                UID = GUID.Generate().ToString();
                UnityEditor.EditorUtility.SetDirty(this);
            }
    #endif
        }
Run Code Online (Sandbox Code Playgroud)

这就是我的做法,它还将可编写脚本的对象设置为脏,这样当您重新启动统一编辑器时它就不会重置。

您可以更进一步,将 UID 字段设为只读,以防止意外更改。

  • 惊人的解决方案。但如果一个项目是重复的,这就会带来一个大问题。这意味着重复的 ID 会很快堆积起来。 (4认同)