Nekopletní fix
This commit is contained in:
250
Game/Scripts/UI/SteamNameTag.cs
Normal file
250
Game/Scripts/UI/SteamNameTag.cs
Normal file
@@ -0,0 +1,250 @@
|
||||
using UnityEngine;
|
||||
using TMPro;
|
||||
using Steamworks;
|
||||
using MegaKoop.Game.Networking;
|
||||
|
||||
namespace MegaKoop.Game.UI
|
||||
{
|
||||
[DefaultExecutionOrder(10000)]
|
||||
[DisallowMultipleComponent]
|
||||
public class SteamNameTag : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Transform followHead;
|
||||
[SerializeField] private Vector3 worldOffset = new Vector3(0f, 2.5f, 0f);
|
||||
[SerializeField] private bool billboardToCamera = true;
|
||||
[SerializeField] private bool hideForLocal = true;
|
||||
[SerializeField] private float visibleDistance = 60f;
|
||||
|
||||
private TextMeshPro text;
|
||||
private Transform tagTransform;
|
||||
private Transform camTransform;
|
||||
private SteamCharacterNetworkBridge bridge;
|
||||
private Callback<PersonaStateChange_t> personaChanged;
|
||||
private ulong lastSteamId;
|
||||
private float camFindTimer;
|
||||
private Coroutine ensureActiveRoutine;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// Reuse existing NameTag child if present (prevents duplicates when cloning templates)
|
||||
var existing = transform.Find("NameTag");
|
||||
GameObject go;
|
||||
if (existing != null)
|
||||
{
|
||||
tagTransform = existing;
|
||||
go = existing.gameObject;
|
||||
}
|
||||
else
|
||||
{
|
||||
go = new GameObject("NameTag");
|
||||
go.layer = gameObject.layer;
|
||||
tagTransform = go.transform;
|
||||
tagTransform.SetParent(transform, worldPositionStays: false);
|
||||
}
|
||||
if (!go.activeSelf) go.SetActive(true);
|
||||
|
||||
text = go.GetComponent<TextMeshPro>();
|
||||
if (text == null)
|
||||
{
|
||||
text = go.AddComponent<TextMeshPro>();
|
||||
}
|
||||
text.alignment = TextAlignmentOptions.Center;
|
||||
text.color = Color.white;
|
||||
text.fontSize = 2.5f;
|
||||
text.enableAutoSizing = true;
|
||||
text.fontSizeMin = 1.5f;
|
||||
text.fontSizeMax = 4.5f;
|
||||
text.text = GetObjectDisplayName();
|
||||
if (!text.gameObject.activeSelf) text.gameObject.SetActive(true);
|
||||
text.enabled = true;
|
||||
|
||||
bridge = GetComponent<SteamCharacterNetworkBridge>();
|
||||
|
||||
if (followHead == null)
|
||||
{
|
||||
followHead = FindChildRecursive(transform, "Head");
|
||||
if (followHead == null)
|
||||
{
|
||||
followHead = transform;
|
||||
worldOffset = new Vector3(0f, 2.5f, 0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetFollowHead(Transform head, SteamCharacterNetworkBridge b)
|
||||
{
|
||||
if (head != null) followHead = head;
|
||||
if (b != null) bridge = b;
|
||||
UpdateDisplayName(true);
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
camTransform = Camera.main != null ? Camera.main.transform : null;
|
||||
TryCreatePersonaCallback();
|
||||
if (tagTransform != null && !tagTransform.gameObject.activeSelf)
|
||||
{
|
||||
tagTransform.gameObject.SetActive(true);
|
||||
}
|
||||
if (text != null)
|
||||
{
|
||||
if (!text.gameObject.activeSelf) text.gameObject.SetActive(true);
|
||||
text.enabled = true;
|
||||
}
|
||||
if (ensureActiveRoutine == null)
|
||||
{
|
||||
ensureActiveRoutine = StartCoroutine(EnsureActiveLoop());
|
||||
}
|
||||
UpdateDisplayName(true);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
personaChanged = null;
|
||||
if (ensureActiveRoutine != null)
|
||||
{
|
||||
StopCoroutine(ensureActiveRoutine);
|
||||
ensureActiveRoutine = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void TryCreatePersonaCallback()
|
||||
{
|
||||
if (personaChanged == null)
|
||||
{
|
||||
personaChanged = Callback<PersonaStateChange_t>.Create(OnPersonaChanged);
|
||||
}
|
||||
}
|
||||
|
||||
private System.Collections.IEnumerator EnsureActiveLoop()
|
||||
{
|
||||
var waiter = new WaitForEndOfFrame();
|
||||
while (isActiveAndEnabled)
|
||||
{
|
||||
if (tagTransform != null && !tagTransform.gameObject.activeSelf)
|
||||
{
|
||||
tagTransform.gameObject.SetActive(true);
|
||||
}
|
||||
if (text != null)
|
||||
{
|
||||
if (!text.gameObject.activeSelf) text.gameObject.SetActive(true);
|
||||
text.enabled = true;
|
||||
}
|
||||
yield return waiter;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPersonaChanged(PersonaStateChange_t cb)
|
||||
{
|
||||
if (bridge == null) return;
|
||||
if (cb.m_ulSteamID == bridge.OwnerSteamId)
|
||||
{
|
||||
UpdateDisplayName(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
camFindTimer -= Time.unscaledDeltaTime;
|
||||
if ((camTransform == null || !camTransform.gameObject.activeInHierarchy) && camFindTimer <= 0f)
|
||||
{
|
||||
var cam = Camera.main;
|
||||
camTransform = cam != null ? cam.transform : null;
|
||||
camFindTimer = 1f;
|
||||
}
|
||||
|
||||
// Never deactivate the NameTag GameObject; only toggle text rendering
|
||||
if (tagTransform != null && !tagTransform.gameObject.activeSelf)
|
||||
{
|
||||
tagTransform.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
Vector3 basePos = followHead != null ? followHead.position : transform.position;
|
||||
tagTransform.position = basePos + worldOffset;
|
||||
|
||||
if (billboardToCamera && camTransform != null)
|
||||
{
|
||||
Vector3 dir = tagTransform.position - camTransform.position;
|
||||
if (dir.sqrMagnitude > 0.001f)
|
||||
{
|
||||
tagTransform.rotation = Quaternion.LookRotation(dir, Vector3.up);
|
||||
}
|
||||
}
|
||||
|
||||
if (text != null)
|
||||
{
|
||||
if (!text.gameObject.activeSelf) text.gameObject.SetActive(true);
|
||||
text.enabled = true;
|
||||
}
|
||||
|
||||
UpdateDisplayName(false);
|
||||
}
|
||||
|
||||
private void UpdateDisplayName(bool force)
|
||||
{
|
||||
if (text == null) return;
|
||||
ulong sid = 0;
|
||||
if (bridge != null) sid = bridge.OwnerSteamId;
|
||||
if (!force && sid == lastSteamId && !string.IsNullOrEmpty(text.text)) return;
|
||||
|
||||
lastSteamId = sid;
|
||||
string display = null;
|
||||
if (sid != 0)
|
||||
{
|
||||
display = ResolvePersonaName(sid);
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(display))
|
||||
{
|
||||
display = GetObjectDisplayName();
|
||||
}
|
||||
if (!string.Equals(text.text, display))
|
||||
{
|
||||
text.text = display;
|
||||
}
|
||||
}
|
||||
|
||||
private string ResolvePersonaName(ulong sid)
|
||||
{
|
||||
if (!SteamBootstrap.IsInitialized)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
ulong local = SteamUser.GetSteamID().m_SteamID;
|
||||
if (sid == local)
|
||||
{
|
||||
return SteamFriends.GetPersonaName();
|
||||
}
|
||||
|
||||
var csid = new CSteamID(sid);
|
||||
string name = SteamFriends.GetFriendPersonaName(csid);
|
||||
if (string.IsNullOrEmpty(name) || name == "???")
|
||||
{
|
||||
SteamFriends.RequestUserInformation(csid, true);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
private string GetObjectDisplayName()
|
||||
{
|
||||
string n = transform.root != null ? transform.root.name : gameObject.name;
|
||||
if (n.StartsWith("Wizard_"))
|
||||
{
|
||||
return n.Substring("Wizard_".Length);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
private static Transform FindChildRecursive(Transform root, string name)
|
||||
{
|
||||
if (root == null) return null;
|
||||
foreach (Transform c in root)
|
||||
{
|
||||
if (c.name == name) return c;
|
||||
var r = FindChildRecursive(c, name);
|
||||
if (r != null) return r;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Game/Scripts/UI/SteamNameTag.cs.meta
Normal file
2
Game/Scripts/UI/SteamNameTag.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 79fb1fbc20d80f546ba695c751860930
|
||||
Reference in New Issue
Block a user