Add player names: settings persistence, replication, screen-space nameplates
- GameSettings: playerName field persisted in Settings.json - NetworkPlayerSetup: owner-written DisplayName NetworkVariable (seeded from settings on spawn, sanitized/truncated, live rename push) - PlayerNameField: binds the session panel name input to settings - PlayerNameplates: screen-space overlay labels above players with distance-based font scaling (clamped min/max), pooling, FP self-hide Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
6db78397da
commit
0e7ce0c410
6 files changed
+252
No files matched your search
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using Unity.Collections;
|
||||
using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
using Chameleon.Components;
|
||||
@@ -80,6 +81,49 @@ public class NetworkPlayerSetup : NetworkBehaviour
|
||||
/// target that is already out of play.</summary>
|
||||
public bool IsFound => _isFound.Value;
|
||||
|
||||
// Owner-published display name (seeded from GameSettings on spawn), consumed by the nameplate overlay
|
||||
// on every client. Empty = unset; DisplayName then falls back to "Player <clientId>".
|
||||
private readonly NetworkVariable<FixedString64Bytes> _displayName =
|
||||
new NetworkVariable<FixedString64Bytes>(default, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner);
|
||||
|
||||
private string _displayNameCache; // resolved lazily, invalidated on replication (no per-frame ToString allocs)
|
||||
|
||||
/// <summary>This avatar's nameplate text: the owner-published name, or "Player <clientId>" when unset.
|
||||
/// Returns the SAME string instance until the name changes, so consumers can change-detect by reference.</summary>
|
||||
public string DisplayName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_displayNameCache == null)
|
||||
{
|
||||
FixedString64Bytes raw = _displayName.Value;
|
||||
_displayNameCache = raw.IsEmpty ? $"Player {OwnerClientId}" : raw.ToString();
|
||||
}
|
||||
return _displayNameCache;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Owner-only: publishes a new display name (trimmed, length-capped) to every client. Called on
|
||||
/// spawn with the persisted settings value and live from the session panel's name field on a rename.</summary>
|
||||
public void PublishDisplayName(string name)
|
||||
{
|
||||
if (!IsOwner || !IsSpawned) return;
|
||||
_displayName.Value = SanitizeName(name);
|
||||
}
|
||||
|
||||
private static FixedString64Bytes SanitizeName(string name)
|
||||
{
|
||||
name = name == null ? "" : name.Trim();
|
||||
const int maxChars = 24;
|
||||
if (name.Length > maxChars) name = name.Substring(0, maxChars);
|
||||
var fs = new FixedString64Bytes();
|
||||
fs.CopyFromTruncated(name); // exotic chars can exceed the 61-byte UTF-8 capacity; truncate, never throw
|
||||
return fs;
|
||||
}
|
||||
|
||||
private void OnDisplayNameChanged(FixedString64Bytes previous, FixedString64Bytes current) =>
|
||||
_displayNameCache = null;
|
||||
|
||||
// Owner-authoritative "this hider is buried too deep" flag: only the OWNER runs the ConcealmentMeter,
|
||||
// so it compares EmbeddedPercent against the threshold and writes; every client reads it to switch
|
||||
// the through-walls X-ray glow.
|
||||
@@ -130,6 +174,7 @@ public class NetworkPlayerSetup : NetworkBehaviour
|
||||
_paintSync = GetComponentInChildren<PlayerPaintSync>(true);
|
||||
_concealment = GetComponentInChildren<ConcealmentMeter>(true);
|
||||
_isFound.OnValueChanged += OnFoundChanged;
|
||||
_displayName.OnValueChanged += OnDisplayNameChanged;
|
||||
if (_isFound.Value) ApplyFound(); // defensive: an avatar is never normally spawned already-found
|
||||
|
||||
// Push the Conversion position into the replicated override before the spawn snapshot goes out.
|
||||
@@ -140,6 +185,8 @@ public class NetworkPlayerSetup : NetworkBehaviour
|
||||
|
||||
if (IsOwner)
|
||||
{
|
||||
PublishDisplayName(GameSettings.PlayerName);
|
||||
|
||||
// Conversion respawn: restore the server-tagged position (the owner-authoritative transform
|
||||
// ignores the server's Instantiate pos); NaN override = normal spawn placement.
|
||||
Vector3 overridePos = _spawnOverride.Value;
|
||||
@@ -195,6 +242,7 @@ public class NetworkPlayerSetup : NetworkBehaviour
|
||||
_active.Remove(this);
|
||||
ActiveVersion++;
|
||||
_isFound.OnValueChanged -= OnFoundChanged;
|
||||
_displayName.OnValueChanged -= OnDisplayNameChanged;
|
||||
}
|
||||
|
||||
/// <summary>Server-only: flag this hider as found by a hunter. Replicates to every client (the body is
|
||||
|
||||
Reference in new issue
Block a user