我有一个持久的game object
,我用它来初始化所有东西。我称之为脚本Persistence
有一些public
引用,我只是通过检查器拖动它们。
我试图让它像我在网上找到的那样持久:
public static Persistence instance;
void Awake()
{
if (instance != null)
{
DestroyImmediate(gameObject);
}
else
{
DontDestroyOnLoad(gameObject);
instance = this;
}
}
问题是,当我从主菜单加载一个级别时,它很好。当我从该级别加载主菜单时,它会显示
MissingReferenceException:类型'持久性'的对象已被破坏,但你仍然试图访问它。
所以我决定在加载主菜单时让它创建其他实例,但这会混淆依赖于这些数据的游戏关卡中的所有脚本。
我的问题是,如果我有检查员添加的引用,如何在Unity中正确实现这个〜单身持久模式?
注意我只从我的持久化类中的Awake
函数初始化,而不是从其他任何地方初始化。从字面上看,我的InitializeMe
脚本是从Persistence
类一个接一个地调用的。
我应该采取哪些不同的方式来完成这项工作?从不同的非持久性gameobject
初始化?忘了拖到检查员?任何建议使这项工作表示赞赏。
答案 0 :(得分:0)
我得到了它的工作。所以这里是人们应该知道的事情(我应该知道),然后再讨论Unity中的持久性:
您不会通过检查器拖动对持久性GO的引用,因为除了添加剂加载之外,当加载另一个场景时它们就会消失。此外,持久性GO可以保存与多个场景相关的数据,保持为通用目的而构建的功能,因为它可以重复使用,但它本身不会初始化任何内容或干扰除了被调用之外的非持久性GO - 用作工具 - 或提供数据。
这种神秘的智慧虽然是我的,所以任何更有技巧的人都会阅读这篇文章,如果我错了,请先纠正我,然后再将其铭记于心。
确切地说,我做了一个非持久性的主人INITIALIZER
来完成确切的事情。我将所有场景变为一次而不是GameObject.Find
。我使用LINQ查询来方便地从该集合中过滤我的结果。另一件事是我的InitializeMe
抽象类(或更确切地说,它的后代)。
public abstract class InitializeMe : MonoBehaviour
{
public int orderNumber;
public abstract void INIT(INITIALIZER init);
}
这里orderNumber用于确定初始化的顺序,如果一个对象依赖于另一个对象。值得一提的是,这样做会导致一种非常可预测的设置方式,因为它是一个接一个地完成的。请注意,这不会产生瓶颈,因为Unity的脚本API只能在主线程中执行 - 将代码划分为多个Awake
或Start
方法对我的最佳知识不会更好。 2017.它由INITIALIZER
中的LINQ查询使用。
INITIALIZER
中的好处是 - 再次 - 它保留了所有,包括对持久对象和保存数据的引用,因此通过引用自身{{1}方法他们可以做他们需要的一切 - 因为InitializeMe
提供了持久数据的通用工具,而DataBank
提供了volatile(希望我使用正确的,我的意思是仅与主菜单相关)数据仅用于主菜单的功能。
现在,持久化不是由持久化类本身确保的,而是由INITIALIZER
中的INITIALIZER
确保如此:
Awake
其中//find by tag or rename upon instantiation as by doing so will result in a "(Clone)" added to its name.
var d = GameObject.FindGameObjectWithTag("DataBank");
if (d == null)
{
//instantiating it
DATA = GameObject.Instantiate<DataBank>(DATA_blueprint);
//intializing the databank itself. The parameters are needed for me,
// but serve as a good example - all of those are dragged from the inspector to the _INITIALIZER_ but will remain in the whole game as long as databank exists.
DATA.LoadDataFromINIT(_baseColor, _baseColor2, _outlineColor,
new MMtoolBundle(DATA));
//to make it persistent.
DontDestroyOnLoad(DATA);
}else
{
//in this case the main menu is loaded from another scene.
//so we only find that loaded object and get its reference, no initialization as it was already setup.
this.DATA = d.GetComponent<DataBank>();
}
是我的持久DATA
。请注意,默认情况下我在场景中有 NO DataBank 对象。 DataBank
是由检查员拖动DATA_blueprint
的预制件(因为DataBank
不是持久的)。它也可以通过INITIALIZER
加载,但这样更方便。
值得一提的是,虽然AssetDatabase
本身就是DataBank
因此它可以出现在Unity场景中,但它的成员都不是MonoBehaviour
所以可以利用继承的力量。如果希望在非单声道工具包中启动MonoBehaviour
,则必须使用coroutine
本身的引用启动。
这种方法的一个明显缺点是我的持续GO的存在取决于DataBank
,因此必须在第一个场景上。但同样,由于大多数游戏都以主菜单开头,这不应该构成一个大问题(谈论单人游戏)。
再来一次我会推荐一些更有技巧的人来纠正我,以防我误导他人,但这个解决方案对我有用 - 在我的所有场景中都没有其他任何东西都是持久的GO创建。