问题描述
我正在 Unity 中创建一个应用程序,在该应用程序中我在运行时从网络导入 JSON 数据库并在 AR 环境中显示信息。
我首先为那只海豚创建了一个名为“Collezione”(意大利语为“Collection”)的存储类,因为我试图让一切尽可能井井有条。 该集合有一个名称和一个展示列表,每个展示都有一个标识符和一个对象列表:
using System.Collections.Generic;
using UnityEngine;
public class Collezione : MonoBehaviour
{
public string nome;
public List<Vetrina> collezione;
}
public class Vetrina
{
public string nome;
public List<ObjectClass> vetrina;
}
public class ObjectClass
{
public string id;
public Vector3 posizione;
public string denominazione;
public string materiale;
public string forma;
public string cronologia;
public string da;
public string a;
}
因为它是一个 MonoBehaviour 类,所以我需要将它附加到一个对象并在所有其他脚本中实例化它的引用。我想知道是否有更有效的方法来做到这一点。我试图将它转换为静态类,它似乎有效,但我想知道是否有更好的解决方案。
这是静态版本。
public static class Collezione
{
public static string nome;
public static List<Vetrina> collezione;
}
public class Vetrina
{
public string nome;
public List<ObjectClass> vetrina;
}
public class ObjectClass
{
public string id;
public Vector3 posizione;
public string denominazione;
public string materiale;
public string forma;
public string cronologia;
public string da;
public string a;
}
解决方法
从您的 Collection 消费者的角度来看,我想说为他们提供一个最干净的方法是使用依赖注入。但是您的两个示例都可以,因为在 Unity 中实现依赖注入并不是一件容易的事。静态类方法可能会好一点,因为当您在其他脚本中使用 GetComponent 时,测试会稍微困难一些。
所以如果你想进行依赖注入,你需要一些组件,负责组合其他组件并注入它们的依赖项。不使用任何 DI 容器框架会有点棘手,但仍然如此。
首先,您可能会引入一个界面来轻松找到您的组件,这需要您的集合:
public interface IConsumatoreDelCollezione
{
public Collezione Collezione { get; set; }
}
只需让需要您的 Collection 的所有组件都实现该接口,包括将数据存储到 Collection 的组件。因此该组件将存储数据,其他读取。
Collection 的实际实现并不重要。它可以是 MonoBehaviour 或 ScriptableObject。但最好的测试只是一个普通的 C# 对象。而您的 MonoBehaviour 组件只会包装该对象。例如像这样:
public class CollezioneComponent : MonoBehaviour
{
public Collezione collezione;
public void Awake()
{
name = "ContenitoreDelCollezione"; // To easily find the container.
}
}
而且您需要一些 CompositionRoot 来自动将它们连接在一起:
public class CompositionRoot : MonoBehaviour
{
public void Awake()
{
var contenitore = Find("ContenitoreDelCollezione").GetComponent<CollezioneComponent>();
var tutti = FindObjectsOfType<GameObject>();
foreach (var obj in tutti)
{
var consumatori = obj.GetComponents<IConsumatoreDelCollezione>();
foreach (var consumatore in consumatori)
{
consumatore.Collezione = contenitore.collezione;
}
}
}
}
重要的是,您不应该在消费者的 Awake 事件期间使用 Collection,因为它可能尚未注入。至少在 Start 中使用它,依此类推。
此外,使用 DI 容器框架(例如 Zenject)可能更容易实现所有这些。所以你可以看看这个。
希望对您有所帮助。