Added better GPS handling, Improved test mode, Fixed naming of players not being broadcast until a new HelloClient, Fixed lobby restarts, Fixed task handling

This commit is contained in:
Bandwidth
2026-04-27 23:18:13 +02:00
parent d886f97e14
commit 207f997254
8 changed files with 1175 additions and 77 deletions

View File

@@ -702,6 +702,20 @@ namespace Subsystems{
_bodyMarkers.Clear();
}
// ── Player avatar sizing ────────────────────────────────────────────
// The default Unity capsule primitive is 2m tall in local space. The
// map camera defaults to 150m orthographic-ish height (see
// MapCameraController), so anything smaller than ~3m world-size is a
// pixel on screen. Original code used scale=0.4 (~0.8m capsule) which
// was invisible. Markers (POIs/tasks/bodies) are 8m pillars; players
// need to be visibly distinct from those AND from each other. The
// local player gets a halo light + larger scale so the user can find
// themselves on the map at a glance.
private const float kLocalPlayerScale = 4f; // ~8m capsule (matches marker height)
private const float kRemotePlayerScale = 2f; // ~4m capsule (smaller than markers)
private const float kLocalPlayerHaloRange = 18f;
private const float kLocalPlayerHaloIntensity = 2.5f;
public void UpdatePlayerAvatars(Dictionary<string, PlayerPositionInfo> positions, string myUuid)
{
if (_mapCenterPoint == null) return;
@@ -715,20 +729,47 @@ namespace Subsystems{
{
string uuid = kvp.Key;
var info = kvp.Value;
bool isLocal = uuid == myUuid;
if (!_playerAvatars.TryGetValue(uuid, out var go) || go == null)
{
go = GameObject.CreatePrimitive(PrimitiveType.Capsule);
go.name = $"Player_{uuid.Substring(0, Mathf.Min(8, uuid.Length))}";
go.transform.parent = _mapCenterPoint?.transform;
go.transform.localScale = Vector3.one * 0.4f;
// Strip the auto-collider - avatars are visual only and the
// collider would interact with the map's MeshColliders.
var col = go.GetComponent<Collider>();
if (col != null) UnityEngine.Object.Destroy(col);
float scale = isLocal ? kLocalPlayerScale : kRemotePlayerScale;
go.transform.localScale = Vector3.one * scale;
if (isLocal)
{
// Halo light around the local player so the user can
// find themselves at a glance even at the widest zoom.
// Range/intensity tuned so it reads as "this is me"
// without bleeding far enough to drown POI markers.
var halo = go.AddComponent<Light>();
halo.color = new Color(0.30f, 1.00f, 0.55f); // matches green capsule color
halo.intensity = kLocalPlayerHaloIntensity;
halo.range = kLocalPlayerHaloRange;
}
_playerAvatars[uuid] = go;
}
go.transform.position = info.Position.ToLocalVector3(_centerPosition) + Vector3.up * 1f;
// Lift the avatar so the bottom of the capsule sits roughly at
// ground level despite the larger scale. Capsule's local pivot
// is at center, height = 2 * localScale.y world units, so we
// raise by half the local height.
float halfHeight = (isLocal ? kLocalPlayerScale : kRemotePlayerScale);
go.transform.position = info.Position.ToLocalVector3(_centerPosition)
+ Vector3.up * halfHeight;
var mr = go.GetComponent<MeshRenderer>();
if (mr)
{
if (uuid == myUuid) mr.material.color = Color.green;
if (isLocal) mr.material.color = new Color(0.30f, 1.00f, 0.55f);
else if (info.State == GeoSus.Client.PlayerState.Dead) mr.material.color = Color.grey;
else mr.material.color = Color.white;
}