开始使用

保存一个值、带默认值把它读回来,并且在这个答案是真的那一刻才去读。

更新于 2026-09-08

安装

首先,通过 VCC(VRChat Creator Companion)把持久化包添加到你的 Unity 项目。打开你项目的 vccproject.json 并添加包,或者使用 VCC 界面直接安装。

安装后,包在你的项目中可用,你就可以开始使用下面的持久化 API 了。

保存

Save.Set("coins", 25);
Save.Set("name", "ada");
Save.Set("spawn", transform.position);

不论什么类型,动词只有一个。用哪一个由值决定,所以没有 SetInt 可以写错。写入永远作用于这个客户端的玩家,因为客户端能改的只有自己的数据。

读回来

int coins = Save.Get("coins", 100);
string name = Save.Get("name", "friend");
Vector3 spawn = Save.Get("spawn", Vector3.zero);

第二个参数是什么都没存时你会拿到的值,而且不能省。 这正是重点:回来的玩家拿到自己的 25 枚,新玩家拿到 100 枚,而代码不需要 TryGetif 就说清了是哪一种。

当这个键里装的类型和你要的不一样时,返回的也是这个值。于是两个都挑了 "level" 这个名字的系统,落到的是默认值而不是一堆没意义的东西。

在正确的时刻读

public class Shop : SaveBehaviour
{
    private int coins;

    public override void OnSaveReady()
    {
        coins = Save.Get("coins", 100);
    }
}

不要在 Start 里读。 保存的数据在玩家加入后不久才到,在那之前读到的一切都是默认值。这个错误值得单写一段,因为它不像个错误:在编辑器里本来往往就没有存过东西,所以直到一个带着真实进度的玩家走进来之前,世界一直按你的意图运行。

继承 SaveBehaviour 就有了 OnSaveReady,它在这个客户端的玩家数据可读的那一刻运行一次。

别人的数据

public override void OnPlayerSaveReady(VRCPlayerApi player)
{
    int theirs = Save.Get(player, "best", 0);
}

你可以读任何人的保存值,但别人的数据变得可读的时刻和你自己的不同:是他们到达的时候,那可能是一小时以后。方法分开正是因为这个——每来一个陌生人就重新加载自己状态的 behaviour,会把这期间做的一切都扔掉。

分辨第一次来和又来了

if (!Save.Has("visits"))
{
    // 发一套欢迎礼。
}

Save.Has 回答这个键有没有被写过。多数时候默认值能更直接地说同一件事;当"没有"本身就是信息时再用它。

两个值得知道的限制

没有办法删除一个键。 VRChat 能覆盖但不能移除,所以一个世界用到的键最好一次定下来,而不是让它慢慢长大。

键在整个世界里是共享的。 两个都保存 "level" 的系统用的是同一个键。给它们加前缀。

出了点问题 重新加载