如何为 3d 模型制作统一的序列化字典?

问题描述 投票:0回答:2
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public struct ImageInfo
{
    public Texture texture;
    public int width;
    public int height;
}

public class ImagesData : MonoBehaviour
{
    public ImageInfo[] images;

    public static Vector2 AspectRatio(float width, float height)
    {
        Vector2 scale = Vector2.one;
    }
}

这是为 2D 图像制作序列化字典的代码,如何使其接受 3D 模型?我希望它像照片中的那样。

c# dictionary unity-game-engine serialization
2个回答
4
投票

这是为二维图像制作序列化字典的代码

不,不是。您显示的是 ImageInfo 的序列化

array

对于您在图像中显示的内容,您可以简单地执行

[Serializable]
public class ModeInfo
{
    public string Id;
    public GameObject Value;
}

public class ModelsDataManager : MonoBehaviour
{
    public ModeInfo[] InteractionModes;
}

或者如果您想要进一步支持一些词典功能

public class ModelsDataManager : MonoBehaviour
{
    [SerializeField]
    private List<ModeInfo> InteractionModes;

    private bool TryGetInfo(string id, out ModeInfo value)
    {
        foreach (var info in InteractionModes)
        {
            if (info.Id == id)
            {
                value = info;
                return true;
            }
        }

        value = default;
        return false;
        
        // or same thing using Linq (needs "using System.Linq;")
        //value = InteractionModes.FirstOrDefault(info => info.Id == id);
        //return value != null;
    }
    
    public bool TryGetValue(string id, out GameObject value)
    {
        if (!TryGetInfo(id, out var info))
        {
            value = default;
            return false;
        }

        // note that just like in normal dictionaries the value can still be "null" though
        value = info.Value;
        return true;
    }

    public void AddOrOverwrite(string id, GameObject value)
    {
        if (!TryGetInfo(id, out var info))
        {
            info = new ModeInfo()
            {
                Id = id
            };

            InteractionModes.Add(info);
        }

        info.Value = value;
    }
}

如果您确实想要使用整个字典功能,包括键检查、更便宜的值访问而无需迭代 等等我建议不要从头开始实现这个,而是使用现有的解决方案,例如


0
投票

这是我的统一可序列化字典的迷你包,具有 Monobehaviour 和 Scriptable Object 变体

https://github.com/Eduard-Malxa/Serialized-Dictionary-Unity

核心脚本

using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class SerializableDictionarySO<TKey, TValue> : ScriptableObject, ISerializationCallbackReceiver
{
    [SerializeField] private List<KeyValueEntry> entries;
    private List<TKey> keys = new List<TKey>();

    public Dictionary<TKey, TValue> dictionary = new Dictionary<TKey, TValue>();

    [Serializable]
    class KeyValueEntry
    {
        public TKey key;
        public TValue value;
    }

    public void OnAfterDeserialize()
    {
        dictionary.Clear();

        for (int i = 0; i < entries.Count; i++)
        {
            dictionary.Add(entries[i].key, entries[i].value);
        }
    }

    public void OnBeforeSerialize()
    {
        if (entries == null)
        {
            return;
        }

        keys.Clear();

        for (int i = 0; i < entries.Count; i++)
        {
            keys.Add(entries[i].key);
        }

        var result = keys.GroupBy(x => x)
                         .Where(g => g.Count() > 1)
                         .Select(x => new { Element = x.Key, Count = x.Count() })
                         .ToList();

        if (result.Count > 0)
        {
            var duplicates = string.Join(", ", result);
            Debug.LogError($"Warning {GetType().FullName} keys has duplicates {duplicates}");
        }
    }
}

public class SerializableDictionary<TKey, TValue> : MonoBehaviour, ISerializationCallbackReceiver
{
    [SerializeField] private List<KeyValueEntry> entries;
    private List<TKey> keys = new List<TKey>();

    public Dictionary<TKey, TValue> dictionary = new Dictionary<TKey, TValue>();

    [Serializable]
    class KeyValueEntry
    {
        public TKey key;
        public TValue value;
    }

    public void OnAfterDeserialize()
    {
        dictionary.Clear();

        for (int i = 0; i < entries.Count; i++)
        {
            dictionary.Add(entries[i].key, entries[i].value);
        }
    }

    public void OnBeforeSerialize()
    {
        if (entries == null)
        {
            return;
        }

        keys.Clear();

        for (int i = 0; i < entries.Count; i++)
        {
            keys.Add(entries[i].key);
        }

        var result = keys.GroupBy(x => x)
                         .Where(g => g.Count() > 1)
                         .Select(x => new { Element = x.Key, Count = x.Count() })
                         .ToList();

        if (result.Count > 0)
        {
            var duplicates = string.Join(", ", result);
            Debug.LogError($"Warning {GetType().FullName} keys has duplicates {duplicates}");
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.