繁体   English   中英

Unity3D 中带有 ScriptableObjects 的复杂数据结构

[英]Complex data structures with ScriptableObjects in Unity3D

我正在尝试创建如图所示的数据结构,我可以在其中轻松添加和删除奖励类型。 这是一个 roguelike 升级系统,基本上我想从特定的稀有度获得特定角色的奖励,比如战士或法师。

与 Unity 相比,我对 Lua 更有经验,在 Lua 语言中,它看起来像这样,

`{
    ["Melee"] = 
    
    {
        [1] = {
            [1] = {"Stat", "Strength", 10},
            [2] = {"Ability", "Swirl", 1},
            
        },
        
        [2] = {
            [1] = {"Stat", "Strength", 50},
            [2] = {"Stat", "PhysicalDefense", 10},
        },
    },
    
    ["Healer"] = 
        {
        [1] = {
            [1] = {"Stat", "MagicalAttack", 5},
            [2] = {"Ability", "Regeneration", 1},
        },

        [2] = {

            [1] = {"Stat", "MagicalDefense", 15},
            [2] = {"Ability", "Regeneration", 1},
        },
    },
}` 

然后为了获得特定的奖励,我会做reward = ["Melee][1][1] 。但是,在 Unity 中,使用字典会禁用 scriptableobject 在编辑器中添加元素的功能。那么我如何创建一个可以添加元素的 scriptableobject在具有相同结构的编辑器中?

您不需要字典来按索引访问项目。

只需使用普通数组或List并执行

public class Warrior : ScriptableObject
{
    public Rarity[] rarities;
}

public class Rarity : ScriptableObject 
{
    public Reward[] rewards;
}

public class Reward : ScriptableObject
{
    public enum RewardType { Stat, Ability }

    public RewardType type;
    public int value;
}

最后在一个

public Warrior[] warriors;

然后,如果第一级确实需要,您仍然可以在运行时设置字典,例如

public Dictionary<string, Warrior> Warriors = new ();

private void Start ()
{
    foreach(var warrior in warriors)
    {
        Warriors.Add(warrior.name, warrior);
    }
}

然后剩下的你会像例如

var reward = Warriors["Melee"].rarities [0].rewards[1];
Debug.Log($"{reward.type} - {reward.name} - {reward.value}");

请记住,在 c# 中索引是基于 0 的


但是,如果您更熟悉自己的方式并且更喜欢通用的字典方法,那么您完全可以这样做!

您可以简单地将其写为 JSON,然后可以在各种 JSON 库中进行选择以再次将其转换为字典。

{
    "Melee" : [
        [ 
            {
                "type":"Stat", 
                "name":"Strength", 
                "value":10
            },
            {
                "type":"Ability", 
                "name":"Swirl",
                "value":1
            }            
        ],
        ...
    ],
    "Healer" : ...
}

那么你就不会使用 ScriptableObject 而只使用例如

[Serializable]
public class Reward
{
    public enum RewardType { Stat, Ability }

    public RewardType type;
    public int value;
    public string name;
}

然后将其反序列化为例如

var Warriors = JsonConvert.DeserializeObject<Dictionary<string, Reward[][]>>(theJsonString);
var reward = Warriors["Melee"][0][0];
Debug.Log($"{reward.type} - {reward.name} - {reward.value}");

可以从文件或 Web 请求等读取theJsonString

此示例使用Newtonsoft JSON.Net ,它可通过包管理器用于 Unity。

就我个人而言,我宁愿使用明确命名的字段和类,而不是那些参差不齐的数组。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM