Carry painting across lobby/map respawns with isolated snapshot transfers
Persist each owner's paint snapshot on the MatchManager across the despawn/respawn that happens on a lobby<->map scene switch, then reload and rebroadcast it onto the freshly spawned avatar so painted meshes survive the transition. Cleared on disconnect/shutdown to avoid stale carry across sessions. Isolate concurrent snapshot transfers by id so a respawning replica's late-join request and the carry broadcast no longer share one reassembly buffer (which decoded a mixed deflate blob -> "Corrupted data"), and drop transfers with an older cutoff so a blank late-join cannot overwrite the carried image. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
b00c415c8c
commit
9d6570f7fe
3 files changed
+120
-8
No files matched your search
@@ -97,6 +97,13 @@ public class MatchManager : MonoBehaviour
|
||||
// client every time. An independent System.Random decouples the pick from that shared global state.
|
||||
private readonly System.Random _roleRng = new System.Random(System.Guid.NewGuid().GetHashCode());
|
||||
|
||||
// Painting carry across an avatar respawn (scene switch). Per-machine: the LOCAL owner's painting,
|
||||
// parked here by its despawning PlayerPaintSync (that component is gone before the replacement spawns)
|
||||
// and consumed once by the next owner avatar. This manager is persistent in Main, so it bridges the
|
||||
// despawn->spawn gap. Cleared on teardown (ReturnToMainOnly) so a fresh session never inherits a
|
||||
// previous one's painting; a normal respawn keeps Main loaded, so the parked copy survives it.
|
||||
private byte[] _carriedPaint;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (Instance && Instance != this) { Destroy(this); return; }
|
||||
@@ -381,6 +388,10 @@ public class MatchManager : MonoBehaviour
|
||||
// active gameplay scene is unloaded, otherwise Unity has no valid active scene to fall back to.
|
||||
private void ReturnToMainOnly()
|
||||
{
|
||||
// A real disconnect/shutdown is not a respawn: drop any parked painting so a fresh session
|
||||
// (re-host / reconnect) never restores a previous match's painting onto its first avatar.
|
||||
_carriedPaint = null;
|
||||
|
||||
Scene main = SceneManager.GetSceneByName(mainSceneName);
|
||||
if (main.IsValid() && main.isLoaded) SceneManager.SetActiveScene(main);
|
||||
|
||||
@@ -400,4 +411,15 @@ public class MatchManager : MonoBehaviour
|
||||
if (s.IsValid() && s.isLoaded && s != SceneManager.GetActiveScene())
|
||||
SceneManager.UnloadSceneAsync(s);
|
||||
}
|
||||
|
||||
/// <summary>Owner-side: park the local painting so the avatar a scene switch spawns next can restore it.</summary>
|
||||
public void StoreCarriedPaint(byte[] data) => _carriedPaint = data;
|
||||
|
||||
/// <summary>Owner-side: take (and clear) the parked painting for the freshly spawned avatar, or null if none.</summary>
|
||||
public byte[] TakeCarriedPaint()
|
||||
{
|
||||
byte[] d = _carriedPaint;
|
||||
_carriedPaint = null;
|
||||
return d;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user