Major updates to the HUD and selectable objects
This commit is contained in:
parent
5bc757b385
commit
c100db52e5
23 changed files with 1615 additions and 614 deletions
|
|
@ -3,6 +3,7 @@ using Unity.Netcode;
|
|||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using TD.Core;
|
||||
using TD.UI;
|
||||
|
||||
namespace TD.Gameplay
|
||||
{
|
||||
|
|
@ -58,10 +59,11 @@ namespace TD.Gameplay
|
|||
"against this layer to determine the move target.")]
|
||||
[SerializeField] private LayerMask buildablePlaneLayerMask;
|
||||
|
||||
[Tooltip("Physics layer mask for the builder selection trigger collider. The " +
|
||||
"builder prefab's child selection collider sits on this layer. The mask " +
|
||||
"must NOT overlap with BuildablePlane or TerrainGeometry; selection is " +
|
||||
"a separate concern.")]
|
||||
[Tooltip("Physics layer mask for selection trigger colliders. Builder selection " +
|
||||
"colliders AND tower selection colliders both sit on this layer. The " +
|
||||
"raycast walks up the hit hierarchy to find an ISelectable component, so " +
|
||||
"any selectable kind on this layer Just Works. The mask must NOT overlap " +
|
||||
"with BuildablePlane or TerrainGeometry; selection is a separate concern.")]
|
||||
[SerializeField] private LayerMask selectionLayerMask;
|
||||
|
||||
[Tooltip("Physics layer mask for build-site visual click targets. The " +
|
||||
|
|
@ -113,12 +115,19 @@ namespace TD.Gameplay
|
|||
if (mouse == null) return;
|
||||
|
||||
bool isPlacing = IsLocalPlayerPlacing();
|
||||
Vector2 mousePos = mouse.position.ReadValue();
|
||||
|
||||
// UI Toolkit dispatches button click events AFTER Update runs, but raw mouse
|
||||
// input is already true this frame. Without this gate, clicking a HUD button
|
||||
// also fires HandleLeftClickSelection — the raycast misses the builder collider
|
||||
// and deselects before the button's action fires. Same risk on right-click.
|
||||
bool pointerOverHud = HUDController.IsPointerOverInteractiveHud(mousePos);
|
||||
|
||||
// Left-click: selection. Suppressed during placement mode (left-click is
|
||||
// the placement-submit gesture there).
|
||||
if (!isPlacing && mouse.leftButton.wasPressedThisFrame)
|
||||
// the placement-submit gesture there) and when the pointer is over HUD.
|
||||
if (!isPlacing && !pointerOverHud && mouse.leftButton.wasPressedThisFrame)
|
||||
{
|
||||
HandleLeftClickSelection(mouse.position.ReadValue());
|
||||
HandleLeftClickSelection(mousePos);
|
||||
}
|
||||
|
||||
// Escape: clear selection. Allowed during placement mode too — Escape never
|
||||
|
|
@ -129,11 +138,12 @@ namespace TD.Gameplay
|
|||
}
|
||||
|
||||
// Right-click. Suppressed entirely during placement mode (TowerPlacementController
|
||||
// handles right-click as cancel-placement there).
|
||||
// handles right-click as cancel-placement there) and when over HUD.
|
||||
if (isPlacing) return;
|
||||
if (pointerOverHud) return;
|
||||
if (!mouse.rightButton.wasPressedThisFrame) return;
|
||||
|
||||
HandleRightClick(mouse.position.ReadValue());
|
||||
HandleRightClick(mousePos);
|
||||
}
|
||||
|
||||
// ----- Selection (left-click) -------------------------------------
|
||||
|
|
@ -147,17 +157,24 @@ namespace TD.Gameplay
|
|||
if (cam == null) return;
|
||||
|
||||
Ray ray = cam.ScreenPointToRay(new Vector3(screenPos.x, screenPos.y, 0f));
|
||||
|
||||
// Single raycast against the unified Selection layer. Whatever we hit, walk
|
||||
// up its hierarchy to find an ISelectable component (Builder, Tower, or
|
||||
// any future kind). The closest hit wins automatically — no priority logic
|
||||
// needed because builders and towers don't visually overlap in practice.
|
||||
if (Physics.Raycast(ray, out RaycastHit hit, raycastMaxDistance, selectionLayerMask))
|
||||
{
|
||||
// Walk up the hierarchy to find a Builder component (the selection
|
||||
// collider may sit on a child of the Builder's root).
|
||||
var hitBuilder = hit.collider.GetComponentInParent<Builder>();
|
||||
|
||||
// Only allow selecting OUR builder. A click on someone else's builder
|
||||
// collider clears our selection rather than selecting theirs.
|
||||
if (hitBuilder != null && hitBuilder == builder)
|
||||
var hitSelectable = hit.collider.GetComponentInParent<ISelectable>();
|
||||
if (hitSelectable != null)
|
||||
{
|
||||
selection.Select(builder);
|
||||
// Don't let players select someone else's builder. Treat that as
|
||||
// "clicked empty" so we clear, rather than steal their selection.
|
||||
if (hitSelectable is Builder b && b != builder)
|
||||
{
|
||||
selection.Clear();
|
||||
return;
|
||||
}
|
||||
selection.Select(hitSelectable);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue