using System; using UnityEngine; namespace XRMultiplayer { [RequireComponent(typeof(XRINetworkPlayer))] public class XRAvatarVisuals : MonoBehaviour { /// /// Head Renderers to change rendering mode for local players. /// [Header("Renderer References"), SerializeField, Tooltip("Head Renderers to change rendering mode for local players.")] protected Renderer[] m_HeadRends; /// /// Head Renderer to control the blend shape for mouth movement. Also updates shirt color based on . /// [SerializeField, Tooltip("Head Renderer to drive mouth movement blendshape and player shirt color.")] protected SkinnedMeshRenderer m_headRend; /// /// GameObject to enable to show what player is the Room Host. /// [Header("Host Visuals"), SerializeField, Tooltip("GameObject that gets enabled for the Host only.")] protected GameObject m_HostVisuals; /// /// GameObject to enable to show what player is the Room Host. /// [SerializeField, Tooltip("Show Host Visuals.")] protected bool m_ShowHostVisuals = true; /// /// Materials to swap for the local player. /// [Header("Local Player Material Swap"), SerializeField] protected LocalPlayerMaterialSwap m_LocalPlayerMaterialSwap; /// /// Reference to the attached XRINetworkPlayerAvatar component. /// protected XRINetworkPlayer m_NetworkPlayerAvatar; public virtual void Awake() { if (!TryGetComponent(out m_NetworkPlayerAvatar)) { Utils.LogError("XRAvatarVisuals requires a XRINetworkPlayerAvatar component to be attached to the same GameObject. Disabling this component now."); enabled = false; return; } m_NetworkPlayerAvatar.onSpawnedLocal += PlayerSpawnedLocal; m_NetworkPlayerAvatar.onSpawnedAll += PlayerSpawnedAll; m_NetworkPlayerAvatar.onColorUpdated += SetPlayerColor; } public virtual void OnDestroy() { m_NetworkPlayerAvatar.onSpawnedLocal -= PlayerSpawnedLocal; m_NetworkPlayerAvatar.onSpawnedAll -= PlayerSpawnedAll; m_NetworkPlayerAvatar.onColorUpdated -= SetPlayerColor; } public virtual void Update() { UpdateMouth(); } public virtual void UpdateMouth() { if (m_headRend != null) m_headRend.SetBlendShapeWeight(0, 100 - (m_NetworkPlayerAvatar.playerVoiceAmp * 100)); } public virtual void PlayerSpawnedLocal() { m_LocalPlayerMaterialSwap.SwapMaterials(); int layer = LayerMask.NameToLayer("Mirror"); foreach (var r in m_HeadRends) { r.gameObject.layer = layer; r.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On; } } public virtual void PlayerSpawnedAll() { m_HostVisuals.SetActive(m_ShowHostVisuals && m_NetworkPlayerAvatar.IsOwnedByServer); } public virtual void SetPlayerColor(Color newColor) { m_headRend.materials[2].SetColor("_BaseColor", newColor); } } } [Serializable] /// /// Helper class for swapping the local player to standard materials from the dithering materials. /// public class LocalPlayerMaterialSwap { public Renderer headRend; public Renderer hmdRend; public Renderer hostRend; public Renderer[] hands; public Material[] headMaterials; public Material[] hmdMaterials; public Material hostMaterial; public Material handMaterial; public void SwapMaterials() { for (int i = 0; i < hands.Length; i++) { hands[i].material = handMaterial; } hmdRend.materials = hmdMaterials; headRend.materials = headMaterials; hostRend.material = hostMaterial; } }