问题描述
普通情况下,当我们想要初始化一个对象的时候,可能会写一个构造方法,通过类的构造方法来进行初始化。当然,实例化一个对象后再对其变量进行访问、赋值也不是不行,只不过这种方式变量就必须开放出来,在一些使用场景中很不安全。Unity中的ScriptableObject并不能像普通对象一样使用new关键字来进行创建,它必须调用ScriptableObject.CreateInstance()方法。以下是官方文档的截图:
可以看到,构造方法的路子行不通,因为Unity在调用CreateInstance的时候是没办法调用构造方法进行初始化的,所以要在创建ScriptableObject的时候对其进行初始化,且可以像构造方法一样安全灵活,有一些法子可以做到这一点。
解决方案
使用静态工厂方法
答案就是创建一个静态方法,该方法返回一个新的ScriptableObject实例,并在其中执行你想要的初始化操作。这个静态方法可以放在ScriptableObject的类定义中,所以你可以访问到类中所有的东西,举个例子:
public class BuffTag : ScriptableObject
{
public int Id {
get; private set; }
public string Name {
get; private set; }
public static BuffTag Create(int id, string name)
{
var newBuffTag = ScriptableObject.CreateInstance<BuffTag>();
newBuffTag.Id = id;
newBuffTag.Name = name;
return newBuffTag;
}
}
假如我们要创建一个Buff系统的Tag,每个Tag以ScriptableObject的形式储存在项目中,为了保证数据安全,我们使用了两个属性,并且通过private修饰符来限制其set访问器的可访问性。这时候如果在类外尝试对ID和Name进行赋值,编译器将会报错。通过创建一个Create静态方法,我们可以在类外创建我们的BuffTag对象,且能对其进行初始化。例如:
var newBuffTag = BuffTag.Create(tagID, tagName);
问题解决。
其实利用该思想,还能做更多的事情,比如追加一个编辑对象的方法之类的,这种就根据需求进行设计了
public class BuffTag : ScriptableObject
{
public int Id {
get; private set; }
public string Name {
get; private set; }
public static BuffTag Create(int id, string name)
{
var newBuffTag = ScriptableObject.CreateInstance<BuffTag>();
newBuffTag.Id = id;
newBuffTag.Name = name;
return newBuffTag;
}
public static BuffTag EditTag(BuffTag buffTag, int id, string name)
{
buffTag.Id = id;
buffTag.Name = name;
buffTag.name = name;
return buffTag;
}
}
在OnEnable方法中初始化
讲到初始化ScriptableObject还是顺便提一下这个,毕竟ScriptableObject也如同MonoBehavior一样,都是继承自Object,在ScriptableObject中同样有不少生命周期函数,包括我们熟悉的OnEnable方法。这个方法在资产被加载时会被调用,你可以使用它来执行初始化操作,不过相比上面的方法就不是很灵活了,不过对于部分需求也是够用。例子如下:
public class BuffTag : ScriptableObject
{
public int Id {
get; private set; }
public string Name {
get; private set; }
private void OnEnable()
{
// 在这里执行初始化操作
Id = 0;
Name = "tag";
}
}