플레이어 오브젝트
플레이어마다 하나씩 주어지고 그 사람과 함께 저장되는 오브젝트, 그리고 올바른 사본을 찾는 방법.
Save는 이름표가 붙은 값들의 서랍입니다. 플레이어 오브젝트는 VRChat이 플레이어마다 하나씩 주고 그 사람을 위해 기억해 두는 GameObject 전체입니다.
어울리는 것이 다릅니다. 인벤토리, 들고 다니는 도구, 설정 패널. 구조가 있는 것, 큰 것, 자주 바뀌는 것. 용량도 따로여서 저장한 값들과 자리를 다투지 않습니다.
만들기
오브젝트를 씬에 두고 VRCPlayerObject 컴포넌트를 붙입니다. VRCEnablePersistence까지 붙이면 그 동기 변수는 방문 사이에 기억됩니다.
여기서 VRChat은 사람들이 걸려 넘어지는 일을 합니다. 당신의 오브젝트는 템플릿이 됩니다. 그것은 비활성화된 채 그 자리에 남고, 플레이어마다 자기 사본을 받습니다. 실행되는 것은 사본입니다. 사본은 사람이 오기 전까지 존재하지 않으므로, 씬 안의 무엇도 사본을 가리킬 수 없습니다.
올바른 사본 찾기
그래서 스크립트는 원하는 인스턴스에 대한 참조를 가질 수 없습니다. 가질 수 있는 것은 템플릿, 즉 인스펙터에 넣을 수 있는 유일한 것입니다. 그다음 어느 사본이 누구의 것인지 묻습니다.
public Inventory template; // 템플릿을 여기에 넣는다
public override void OnSaveReady()
{
Inventory mine = PlayerObjects.Mine(template);
mine.Add("hat");
}
다른 사람의 것은 이렇게 얻습니다.
Inventory theirs = PlayerObjects.Of(player, template);
인자 없는 PlayerObjects.Mine()은 이 클라이언트의 플레이어에게 속한 오브젝트를 모두 돌려줍니다. 직접 훑어보고 싶을 때 쓰세요.
소유권
플레이어는 자기 사본을 소유하며 그것은 넘길 수 없습니다. 누군가 남의 물건을 들고 가는 것을 막는 규칙이고, 동시에 플레이어 오브젝트를 바꾸기 전에 소유권을 요청할 필요가 없다는 뜻이기도 합니다.
타이밍 규칙은 같습니다
플레이어 오브젝트가 저장값을 불러오는 순간은 저장값이 도착하는 순간과 같습니다. 그러니 여기서도 읽는 자리는 OnSaveReady입니다. Start에서 읽으면 데이터가 닿기 전 오브젝트의 모습이 돌아옵니다.
용량
저장값에 약 100 KB, 플레이어 오브젝트에 다시 100 KB, 모두 플레이어마다입니다. 넘겨도 월드는 멈추지 않습니다. VRChat이 오류를 기록하고 저장을 그만두므로, 계속 돌아가면서 조용히 기억하기를 멈춥니다.
public override void OnPersistenceUsageUpdated()
{
int used = Storage.SaveUsed();
int limit = Storage.SaveLimit;
}
이 숫자는 여기서 읽고 다른 곳에서는 읽지 마세요. 늘 유지되는 것이 아니라 이따금 다시 계산되는 값이고, 첫 계산 전에는 0을 돌려줍니다. 그것은 "아직 세지 않았다"이지 "자리가 없다"가 아닙니다. OnPlayerDataStorageWarning을 override해 두면 아직 손 쓸 수 있을 때 어떤 플레이어가 한계에 가까워졌음을 알 수 있습니다.