feat: isolate lobby during minigames

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
ud18010
2026-07-29 15:26:54 +08:00
co-authored by Claude Opus 4.8
parent 31afce6882
commit 6a5e534d00
9 changed files with 1408 additions and 8 deletions
@@ -0,0 +1,113 @@
using NUnit.Framework;
using UnityEngine;
using XGame.MiniGame;
public sealed class MiniGameStageIsolationTests
{
private GameObject _root;
private sealed class TestBehaviour : MonoBehaviour
{
}
[TearDown]
public void TearDown()
{
if (_root != null)
{
Object.DestroyImmediate(_root);
_root = null;
}
}
[Test]
public void SuspendAndResume_RestoresOriginalActiveAndEnabledStates()
{
_root = new GameObject("root");
GameObject uiActive = new GameObject("ui-active");
GameObject uiInactive = new GameObject("ui-inactive");
GameObject sceneRoot = new GameObject("scene-root");
uiActive.transform.SetParent(_root.transform);
uiInactive.transform.SetParent(_root.transform);
sceneRoot.transform.SetParent(_root.transform);
uiInactive.SetActive(false);
var enabledInput = _root.AddComponent<TestBehaviour>();
var disabledTick = _root.AddComponent<TestBehaviour>();
disabledTick.enabled = false;
var canvas = _root.AddComponent<CanvasGroup>();
canvas.interactable = true;
canvas.blocksRaycasts = true;
var isolation = _root.AddComponent<MiniGameStageIsolation>();
isolation.LobbyUiRoots = new[] { uiActive, uiInactive };
isolation.LobbySceneRoots = new[] { sceneRoot };
isolation.LobbyInputBehaviours = new Behaviour[] { enabledInput };
isolation.LobbyTickBehaviours = new Behaviour[] { disabledTick };
isolation.LobbyCanvasGroups = new[] { canvas };
isolation.SuspendLobbyForMiniGame();
Assert.IsTrue(isolation.IsSuspended);
Assert.IsFalse(uiActive.activeSelf);
Assert.IsFalse(uiInactive.activeSelf);
Assert.IsFalse(sceneRoot.activeSelf);
Assert.IsFalse(enabledInput.enabled);
Assert.IsFalse(disabledTick.enabled);
Assert.IsFalse(canvas.interactable);
Assert.IsFalse(canvas.blocksRaycasts);
isolation.ResumeLobbyAfterMiniGame();
Assert.IsFalse(isolation.IsSuspended);
Assert.IsTrue(uiActive.activeSelf);
Assert.IsFalse(uiInactive.activeSelf);
Assert.IsTrue(sceneRoot.activeSelf);
Assert.IsTrue(enabledInput.enabled);
Assert.IsFalse(disabledTick.enabled);
Assert.IsTrue(canvas.interactable);
Assert.IsTrue(canvas.blocksRaycasts);
}
[Test]
public void SuspendAndResume_AreIdempotent()
{
_root = new GameObject("root");
GameObject ui = new GameObject("ui");
ui.transform.SetParent(_root.transform);
var behaviour = _root.AddComponent<TestBehaviour>();
var isolation = _root.AddComponent<MiniGameStageIsolation>();
isolation.LobbyUiRoots = new[] { ui };
isolation.LobbyInputBehaviours = new Behaviour[] { behaviour };
isolation.SuspendLobbyForMiniGame();
ui.SetActive(true);
behaviour.enabled = true;
isolation.SuspendLobbyForMiniGame();
Assert.IsFalse(ui.activeSelf);
Assert.IsFalse(behaviour.enabled);
isolation.ResumeLobbyAfterMiniGame();
isolation.ResumeLobbyAfterMiniGame();
Assert.IsTrue(ui.activeSelf);
Assert.IsTrue(behaviour.enabled);
}
[Test]
public void SuspendAndResume_IgnoreNullEntries()
{
_root = new GameObject("root");
var isolation = _root.AddComponent<MiniGameStageIsolation>();
isolation.LobbyUiRoots = new GameObject[] { null };
isolation.LobbySceneRoots = new GameObject[] { null };
isolation.LobbyInputBehaviours = new Behaviour[] { null };
isolation.LobbyTickBehaviours = new Behaviour[] { null };
isolation.LobbyCanvasGroups = new CanvasGroup[] { null };
Assert.DoesNotThrow(() => isolation.SuspendLobbyForMiniGame());
Assert.DoesNotThrow(() => isolation.ResumeLobbyAfterMiniGame());
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0db89d5629e34042af0af9a432d1efb7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: