持久化
保存玩家的进度,用两个动词而不是十六种方法,时机上的坑也替你处理好了。
VRChat 可以在两次到访之间记住关于一个玩家的事情。它为此给你的 API 是一个按类型分方法的键值存储:SetInt、GetInt、TryGetInt,同样的三个又为十六种类型各来一遍。
其中有三件事会悄悄出错。
你得记住是哪个方法写了这个键。 用 SetInt 写的 "level" 再用 GetString 去读,不会有任何抱怨:你拿到一个空字符串,然后照常往下走。
对没人写过的键,GetInt 返回零,而保存下来的零也长这样。一个给新玩家发起始资金的商店,分不出第一次来的人和把钱花光的人。
在 Start 里保存的数据还没到。 它在玩家进来之后一小会儿才到。读得太早不会报错,只会拿到默认值,所以在没有东西可恢复的编辑器里世界表现得完美无缺,然后把一个带着进度的真玩家当成陌生人接待。
这个包是两个动词和一个基类:
public class Shop : SaveBehaviour
{
private int coins;
public override void OnSaveReady()
{
coins = Save.Get("coins", 100);
}
public void Buy(int price)
{
coins = coins - price;
Save.Set("coins", coins);
}
}
其余的由值来决定。Save.Set("name", "ada") 存字符串,Save.Set("coins", 5) 存整数,你都不必点名是哪一种。读取时要一并给出"什么都没存时该拿到的值",那正是你本来会写在 TryGet 下面那个 if 里的值——而强制你写出它,正是把"从未保存"和"保存成了零"分开的东西。
OnSaveReady 在读取唯一有意义的那一刻运行。把加载放在那里而不是 Start,顺序就不再是你需要记住的事。
里面有什么
Save |
Set 与 Get,覆盖 VRChat 能保存的每一种类型 |
SaveBehaviour |
在数据成真的那一刻运行的 OnSaveReady |
PlayerObjects |
找到属于某个玩家的那份副本 |
Storage |
世界为这个玩家用掉了多少配额 |