Adding new Races, Main Menu -> Lobby flow, and what's needed to set up multiplayer testing.
This commit is contained in:
parent
60fa58b07f
commit
fdada6f132
29 changed files with 2581 additions and 176 deletions
|
|
@ -1,7 +1,10 @@
|
|||
// Assets/_Project/Scripts/UI/MainMenuController.cs
|
||||
using System.Collections;
|
||||
using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using TD.Core;
|
||||
using TD.Gameplay;
|
||||
using TD.Net;
|
||||
|
||||
namespace TD.UI
|
||||
|
|
@ -44,6 +47,7 @@ namespace TD.UI
|
|||
private Button hostButton;
|
||||
private Button joinButton;
|
||||
private Button quitButton;
|
||||
private Button quickStartButton;
|
||||
private VisualElement joinPanel;
|
||||
private TextField joinAddressField;
|
||||
private TextField joinPortField;
|
||||
|
|
@ -96,12 +100,14 @@ namespace TD.UI
|
|||
buttonColumn.style.alignItems = Align.Center;
|
||||
root.Add(buttonColumn);
|
||||
|
||||
hostButton = MakeMenuButton("Host Game", OnHostClicked);
|
||||
joinButton = MakeMenuButton("Join Game", OnJoinClicked);
|
||||
quitButton = MakeMenuButton("Quit", OnQuitClicked);
|
||||
hostButton = MakeMenuButton("Host Game", OnHostClicked);
|
||||
joinButton = MakeMenuButton("Join Game", OnJoinClicked);
|
||||
quitButton = MakeMenuButton("Quit", OnQuitClicked);
|
||||
quickStartButton = MakeMenuButton("Quick Start", OnQuickStartClicked);
|
||||
buttonColumn.Add(hostButton);
|
||||
buttonColumn.Add(joinButton);
|
||||
buttonColumn.Add(quitButton);
|
||||
buttonColumn.Add(quickStartButton);
|
||||
|
||||
// Join sub-panel — hidden until Join is clicked. Holds the IP+port
|
||||
// fields and the Connect / Cancel buttons.
|
||||
|
|
@ -120,14 +126,14 @@ namespace TD.UI
|
|||
joinAddressField = new TextField("Host address");
|
||||
joinAddressField.value = defaultJoinAddress;
|
||||
joinAddressField.style.width = 280;
|
||||
joinAddressField.style.color = Color.white;
|
||||
StyleJoinFieldText(joinAddressField);
|
||||
joinPanel.Add(joinAddressField);
|
||||
|
||||
joinPortField = new TextField("Port");
|
||||
joinPortField.value = defaultPort.ToString();
|
||||
joinPortField.style.width = 280;
|
||||
joinPortField.style.marginTop = 8;
|
||||
joinPortField.style.color = Color.white;
|
||||
StyleJoinFieldText(joinPortField);
|
||||
joinPanel.Add(joinPortField);
|
||||
|
||||
var joinButtons = new VisualElement();
|
||||
|
|
@ -154,6 +160,19 @@ namespace TD.UI
|
|||
root.Add(statusLabel);
|
||||
}
|
||||
|
||||
// TextField's visible text color lives on the inner "unity-text-input"
|
||||
// element, not on the TextField root. Setting it on the root alone
|
||||
// leaves the inner element's inherited white color in place — which is
|
||||
// invisible against the default white input background. Same gotcha as
|
||||
// the chat input's dark-styling path in HUDController.
|
||||
private static void StyleJoinFieldText(TextField field)
|
||||
{
|
||||
field.style.color = Color.black;
|
||||
var inner = field.Q("unity-text-input");
|
||||
if (inner != null)
|
||||
inner.style.color = Color.black;
|
||||
}
|
||||
|
||||
private static Button MakeMenuButton(string text, System.Action onClick)
|
||||
{
|
||||
var btn = new Button(() => onClick?.Invoke()) { text = text };
|
||||
|
|
@ -229,5 +248,53 @@ namespace TD.UI
|
|||
Application.Quit();
|
||||
#endif
|
||||
}
|
||||
|
||||
// Dev / testing shortcut: skips the lobby entirely. Hosts a single-player
|
||||
// session, auto-selects Race1 for the local player, and loads the Match
|
||||
// scene directly. Useful for iterating on gameplay without clicking
|
||||
// through Host → Lobby → Pick Race → Ready → Start every time.
|
||||
//
|
||||
// To remove for a shipping build: delete the button-creation lines in
|
||||
// BuildUI plus this method and its coroutine. No other consumers.
|
||||
private void OnQuickStartClicked()
|
||||
{
|
||||
statusLabel.text = "Quick starting…";
|
||||
StartCoroutine(QuickStartCoroutine());
|
||||
}
|
||||
|
||||
private IEnumerator QuickStartCoroutine()
|
||||
{
|
||||
if (!NetworkBootstrap.StartHost(defaultPort))
|
||||
{
|
||||
statusLabel.text = "Failed to start host. Check the console.";
|
||||
yield break;
|
||||
}
|
||||
|
||||
// Wait for the local player's PlayerMatchState to spawn. Empirically
|
||||
// this happens synchronously inside StartHost, but waiting one frame
|
||||
// is cheap insurance against future NGO changes to spawn timing.
|
||||
// Cap the wait at 60 frames so a real failure doesn't silently hang.
|
||||
int safetyFrames = 0;
|
||||
while (PlayerMatchState.Local == null && safetyFrames++ < 60)
|
||||
yield return null;
|
||||
|
||||
var pms = PlayerMatchState.Local;
|
||||
if (pms == null)
|
||||
{
|
||||
Debug.LogError("[MainMenuController] Quick Start: PlayerMatchState.Local " +
|
||||
"didn't appear within 60 frames after StartHost. Aborting.");
|
||||
statusLabel.text = "Quick Start failed: player did not spawn.";
|
||||
yield break;
|
||||
}
|
||||
|
||||
// Server-only setters — host is server + client, so these are valid
|
||||
// directly. Skipping the RPC round-trip avoids any frame-of-latency
|
||||
// before LoadSceneAsHost reads RaceSelection on the way into Match.
|
||||
pms.SetRaceSelection(RaceId.Race1);
|
||||
pms.SetReady(true);
|
||||
|
||||
// Skip Lobby — drop straight into the Match scene.
|
||||
NetworkBootstrap.LoadSceneAsHost(SceneNames.Match);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue