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
|
|
@ -43,8 +43,18 @@ namespace TD.Gameplay
|
|||
/// <c>TowerCombat</c> component added to the same prefab.</para>
|
||||
/// </remarks>
|
||||
[RequireComponent(typeof(NetworkObject))]
|
||||
public class TowerInstance : NetworkBehaviour, IMinimapEntity
|
||||
public class TowerInstance : NetworkBehaviour, IMinimapEntity, ISelectable
|
||||
{
|
||||
// ----- Inspector --------------------------------------------------
|
||||
|
||||
[Header("Visuals")]
|
||||
[Tooltip("Mesh renderers tinted with the owner's player color. " +
|
||||
"Drag in only the tower body's renderers — exclude anything " +
|
||||
"that has its own color rules (selection rings, range " +
|
||||
"indicators, FX). If left empty, the tower is NOT tinted " +
|
||||
"and the prefab's baked materials show through.")]
|
||||
[SerializeField] private MeshRenderer[] tintedRenderers;
|
||||
|
||||
// ----- Networked state ------------------------------------------------
|
||||
|
||||
// The name of the TowerDefinition asset for this tower. Replicated so all
|
||||
|
|
@ -107,6 +117,40 @@ namespace TD.Gameplay
|
|||
/// <summary>The footprint anchor tile (SW corner, world-tile coords).</summary>
|
||||
public Vector2Int AnchorTile => anchorTile.Value;
|
||||
|
||||
// ----- ISelectable ----------------------------------------------------
|
||||
|
||||
// Absolute world-unit margin that the selection ring extends beyond the
|
||||
// tower's footprint edges. Tuned for visibility — the tower body sits ON
|
||||
// the ring at ground level, so only the area outside the footprint is
|
||||
// actually rendered. Too small (was 0.15) and the ring is invisible under
|
||||
// anything taller than a paving stone. 0.5 gives a half-tile-wide visible
|
||||
// band around the tower at any footprint size.
|
||||
private const float SelectionRingPadding = 0.5f;
|
||||
|
||||
/// <summary>Display name shown in the HUD portrait when this tower is selected.</summary>
|
||||
public string DisplayName =>
|
||||
resolvedDefinition != null ? resolvedDefinition.DisplayName : "Tower";
|
||||
|
||||
public SelectableKind Kind => SelectableKind.Tower;
|
||||
|
||||
public Transform SelectionTransform => transform;
|
||||
|
||||
// Ring radius derived from footprint: max axis * 0.5 * tile size, plus a
|
||||
// small padding so the ring is visible outside the tower's edges. Falls
|
||||
// back to 1×1 if the definition hasn't resolved yet (transient, harmless —
|
||||
// the HUD won't allow selection until OnNetworkSpawn finishes anyway).
|
||||
public float SelectionRadius
|
||||
{
|
||||
get
|
||||
{
|
||||
Vector2Int fp = resolvedDefinition != null
|
||||
? resolvedDefinition.FootprintSize
|
||||
: new Vector2Int(1, 1);
|
||||
return Mathf.Max(fp.x, fp.y) * 0.5f * GridCoordinates.TILE_SIZE
|
||||
+ SelectionRingPadding;
|
||||
}
|
||||
}
|
||||
|
||||
// ----- Server-only initialization -------------------------------------
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -171,6 +215,20 @@ namespace TD.Gameplay
|
|||
// Register for minimap rendering.
|
||||
MinimapEntityRegistry.Register(this);
|
||||
|
||||
// Selection auto-transfer: if a BuildSiteVisual at our anchor is the
|
||||
// active local selection, the player was watching this tower complete —
|
||||
// hand selection off to the new TowerInstance so the HUD/visualizer
|
||||
// transition smoothly. Server's completion order (spawn THEN despawn)
|
||||
// means we get here BEFORE the BuildSiteVisual's OnNetworkDespawn,
|
||||
// so the old reference is still valid and selected.
|
||||
var selState = SelectionState.Instance;
|
||||
if (selState != null
|
||||
&& selState.SelectedObject is BuildSiteVisual bsv
|
||||
&& bsv.Anchor == anchorTile.Value)
|
||||
{
|
||||
selState.Select(this);
|
||||
}
|
||||
|
||||
if (resolvedDefinition != null)
|
||||
{
|
||||
Debug.Log($"[TowerInstance] Spawned '{resolvedDefinition.DisplayName}' " +
|
||||
|
|
@ -186,6 +244,13 @@ namespace TD.Gameplay
|
|||
StampFootprint(walkable: true, occupied: false);
|
||||
|
||||
MinimapEntityRegistry.Deregister(this);
|
||||
|
||||
// Clear local selection if THIS tower was selected. Without this,
|
||||
// SelectionState (and any subscriber holding our reference — HUD,
|
||||
// SelectionVisualizer) keeps pointing at a soon-to-be-destroyed Unity
|
||||
// object and throws MissingReferenceException on the next access.
|
||||
if (SelectionState.Instance != null && SelectionState.Instance.IsSelected(this))
|
||||
SelectionState.Instance.Clear();
|
||||
}
|
||||
|
||||
// ----- IMinimapEntity -------------------------------------------------
|
||||
|
|
@ -285,19 +350,20 @@ namespace TD.Gameplay
|
|||
|
||||
// MaterialPropertyBlock sets per-renderer properties without allocating
|
||||
// a new Material object. Safe to reuse across calls on the same instance.
|
||||
// All Unity standard/URP shaders expose _Color or _BaseColor, so no shader changes needed.
|
||||
// All Unity standard/URP shaders expose _Color or _BaseColor, so writing
|
||||
// both lets the tint apply regardless of which shader the prefab uses.
|
||||
colorPropertyBlock ??= new MaterialPropertyBlock();
|
||||
colorPropertyBlock.SetColor(ColorPropertyId, ownerColor);
|
||||
colorPropertyBlock.SetColor(BaseColorPropertyId, ownerColor);
|
||||
|
||||
var renderers = GetComponentsInChildren<MeshRenderer>();
|
||||
foreach (var rend in renderers)
|
||||
rend.SetPropertyBlock(colorPropertyBlock);
|
||||
|
||||
if (renderers.Length == 0)
|
||||
// Tint only the renderers explicitly listed in the inspector. Avoids
|
||||
// accidentally re-coloring decorative children, FX, etc. (Mirrors
|
||||
// Builder.tintedRenderers — same rationale.)
|
||||
if (tintedRenderers == null) return;
|
||||
foreach (var rend in tintedRenderers)
|
||||
{
|
||||
Debug.LogWarning($"[TowerInstance] NetworkObject {NetworkObjectId}: " +
|
||||
$"No MeshRenderers found for owner color tinting.");
|
||||
if (rend == null) continue;
|
||||
rend.SetPropertyBlock(colorPropertyBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue