Support styled multi-text nameplate label containers
PlayerNameplates clones a GameObject container instead of a single TMP_Text and drives all TMP_Text children (text + distance font size), so the label template can be authored with layered texts (e.g. outline or shadow copies) in the editor. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4c6a452f9d
commit
0ab92933de
1 file changed
+15
-14
@@ -17,7 +17,7 @@ public class PlayerNameplates : MonoBehaviour
|
|||||||
{
|
{
|
||||||
[Tooltip("Disabled label prototype under this canvas; cloned once per avatar. Author pivot (0.5, 0) + " +
|
[Tooltip("Disabled label prototype under this canvas; cloned once per avatar. Author pivot (0.5, 0) + " +
|
||||||
"bottom-center alignment so the text sits on top of the head anchor.")]
|
"bottom-center alignment so the text sits on top of the head anchor.")]
|
||||||
[SerializeField] private TMP_Text labelTemplate;
|
[SerializeField] private GameObject labelContainerTemplate;
|
||||||
|
|
||||||
[Tooltip("Metres above the avatar's capsule top where the name anchors.")]
|
[Tooltip("Metres above the avatar's capsule top where the name anchors.")]
|
||||||
[SerializeField] private float heightOffset = 0.1f;
|
[SerializeField] private float heightOffset = 0.1f;
|
||||||
@@ -38,7 +38,8 @@ public class PlayerNameplates : MonoBehaviour
|
|||||||
private class Entry
|
private class Entry
|
||||||
{
|
{
|
||||||
public NetworkPlayerSetup setup;
|
public NetworkPlayerSetup setup;
|
||||||
public TMP_Text label;
|
public GameObject labelContainer;
|
||||||
|
public TMP_Text[] labels;
|
||||||
public CharacterController capsule; // head-anchor height (present but disabled on remotes)
|
public CharacterController capsule; // head-anchor height (present but disabled on remotes)
|
||||||
public Renderer body; // own-avatar gate: first-person self-hides the mesh
|
public Renderer body; // own-avatar gate: first-person self-hides the mesh
|
||||||
public string lastText;
|
public string lastText;
|
||||||
@@ -50,12 +51,12 @@ public class PlayerNameplates : MonoBehaviour
|
|||||||
|
|
||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
if (labelTemplate) labelTemplate.gameObject.SetActive(false);
|
if (labelContainerTemplate) labelContainerTemplate.SetActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LateUpdate()
|
private void LateUpdate()
|
||||||
{
|
{
|
||||||
if (!labelTemplate) return;
|
if (!labelContainerTemplate) return;
|
||||||
|
|
||||||
if (_seenVersion != NetworkPlayerSetup.ActiveVersion)
|
if (_seenVersion != NetworkPlayerSetup.ActiveVersion)
|
||||||
{
|
{
|
||||||
@@ -73,7 +74,7 @@ public class PlayerNameplates : MonoBehaviour
|
|||||||
for (int i = 0; i < _entries.Count; i++)
|
for (int i = 0; i < _entries.Count; i++)
|
||||||
{
|
{
|
||||||
Entry e = _entries[i];
|
Entry e = _entries[i];
|
||||||
if (!e.setup || !e.label) continue;
|
if (!e.setup || !e.labelContainer || e.labels is null || e.labels.Length == 0) continue;
|
||||||
|
|
||||||
bool show = cam;
|
bool show = cam;
|
||||||
|
|
||||||
@@ -95,11 +96,11 @@ public class PlayerNameplates : MonoBehaviour
|
|||||||
else distance = Vector3.Distance(cam.transform.position, anchor);
|
else distance = Vector3.Distance(cam.transform.position, anchor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.label.gameObject.activeSelf != show)
|
if (e.labelContainer.activeSelf != show)
|
||||||
e.label.gameObject.SetActive(show);
|
e.labelContainer.SetActive(show);
|
||||||
if (!show) continue;
|
if (!show) continue;
|
||||||
|
|
||||||
e.label.transform.position = new Vector3(screen.x, screen.y, 0f);
|
e.labelContainer.transform.position = new Vector3(screen.x, screen.y, 0f);
|
||||||
|
|
||||||
float size = Mathf.Clamp(referenceFontSize * referenceDistance / Mathf.Max(distance, 0.01f),
|
float size = Mathf.Clamp(referenceFontSize * referenceDistance / Mathf.Max(distance, 0.01f),
|
||||||
minFontSize, maxFontSize);
|
minFontSize, maxFontSize);
|
||||||
@@ -107,13 +108,13 @@ public class PlayerNameplates : MonoBehaviour
|
|||||||
if (Mathf.Abs(size - e.lastSize) > 0.05f)
|
if (Mathf.Abs(size - e.lastSize) > 0.05f)
|
||||||
{
|
{
|
||||||
e.lastSize = size;
|
e.lastSize = size;
|
||||||
e.label.fontSize = size;
|
foreach (var label in e.labels) label.fontSize = size;
|
||||||
}
|
}
|
||||||
string text = e.setup.DisplayName; // same instance until renamed -> reference compare suffices
|
string text = e.setup.DisplayName; // same instance until renamed -> reference compare suffices
|
||||||
if (!ReferenceEquals(text, e.lastText))
|
if (!ReferenceEquals(text, e.lastText))
|
||||||
{
|
{
|
||||||
e.lastText = text;
|
e.lastText = text;
|
||||||
e.label.text = text;
|
foreach (var label in e.labels) label.text = text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -130,7 +131,7 @@ public class PlayerNameplates : MonoBehaviour
|
|||||||
private void Rebuild()
|
private void Rebuild()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < _entries.Count; i++)
|
for (int i = 0; i < _entries.Count; i++)
|
||||||
if (_entries[i].label) Destroy(_entries[i].label.gameObject);
|
if (_entries[i].labelContainer) Destroy(_entries[i].labelContainer);
|
||||||
_entries.Clear();
|
_entries.Clear();
|
||||||
|
|
||||||
var avatars = NetworkPlayerSetup.Active;
|
var avatars = NetworkPlayerSetup.Active;
|
||||||
@@ -139,12 +140,12 @@ public class PlayerNameplates : MonoBehaviour
|
|||||||
var setup = avatars[i];
|
var setup = avatars[i];
|
||||||
if (!setup) continue;
|
if (!setup) continue;
|
||||||
|
|
||||||
var label = Instantiate(labelTemplate, labelTemplate.transform.parent);
|
var labelContainer = Instantiate(labelContainerTemplate, labelContainerTemplate.transform.parent);
|
||||||
label.raycastTarget = false;
|
|
||||||
_entries.Add(new Entry
|
_entries.Add(new Entry
|
||||||
{
|
{
|
||||||
setup = setup,
|
setup = setup,
|
||||||
label = label,
|
labelContainer = labelContainer,
|
||||||
|
labels = labelContainer.GetComponentsInChildren<TMP_Text>(),
|
||||||
capsule = setup.GetComponent<CharacterController>(),
|
capsule = setup.GetComponent<CharacterController>(),
|
||||||
body = setup.GetComponentInChildren<SkinnedMeshRenderer>(true),
|
body = setup.GetComponentInChildren<SkinnedMeshRenderer>(true),
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in new issue
Block a user