using UnityEngine;
///
/// Attached to the group leader's GameObject.
/// Scales the leader's sphere to reflect group size and renders a floating
/// count label above it using a World-Space Canvas + TextMesh.
/// Follower agents are hidden (renderer disabled) while in the group.
///
[RequireComponent(typeof(MeshRenderer))]
public class AgentGroupVisual : MonoBehaviour
{
private AgentGroup group;
private MeshRenderer meshRenderer;
private GameObject labelObject;
private TextMesh countLabel;
// Base scale of a solo agent is 0.5 (set in CreateDefaultAgentPrefab)
private const float BASE_SCALE = 0.5f;
// Each additional member adds 10% to radius (so group of 9 is ~1.4× base)
private const float SCALE_GROWTH = 0.1f;
private static readonly Color SOLO_COLOR = Color.cyan;
private static readonly Color GROUP_COLOR = new Color(1f, 0.55f, 0f); // orange
public void Init(AgentGroup g)
{
group = g;
meshRenderer = GetComponent();
CreateLabel();
Refresh();
}
public void Refresh()
{
if (group == null) return;
int size = group.Size;
// Scale sphere
float scale = BASE_SCALE + BASE_SCALE * SCALE_GROWTH * (size - 1);
transform.localScale = Vector3.one * scale;
// Color: solo = cyan, grouped = orange, larger group = brighter orange
meshRenderer.material.color = size > 1 ? GROUP_COLOR : SOLO_COLOR;
// Count label – only show for groups of 2+
if (labelObject != null)
{
labelObject.SetActive(size > 1);
if (countLabel != null) countLabel.text = size.ToString();
}
// Hide/show follower renderers
foreach (var member in group.Members)
{
if (member == group.Leader) continue;
var mr = member.GetComponent();
if (mr != null) mr.enabled = false;
var lr = member.GetComponent();
if (lr != null) lr.enabled = false;
}
}
private void CreateLabel()
{
labelObject = new GameObject("GroupCountLabel");
labelObject.transform.SetParent(transform, false);
// Float above the sphere
labelObject.transform.localPosition = new Vector3(0f, 0.8f, 0f);
countLabel = labelObject.AddComponent();
countLabel.text = "1";
countLabel.fontSize = 48;
countLabel.alignment = TextAlignment.Center;
countLabel.anchor = TextAnchor.MiddleCenter;
countLabel.color = Color.white;
countLabel.characterSize = 0.05f;
// Always face camera
labelObject.AddComponent();
}
void OnDestroy()
{
if (labelObject != null) Destroy(labelObject);
// Restore solo scale/color if visual is removed (member left group)
transform.localScale = Vector3.one * BASE_SCALE;
if (meshRenderer != null) meshRenderer.material.color = SOLO_COLOR;
}
}
/// Keeps the TextMesh facing the main camera.
public class BillboardLabel : MonoBehaviour
{
void LateUpdate()
{
if (Camera.main == null) return;
transform.forward = Camera.main.transform.forward;
}
}