using UdonSharp; using UnityEngine; using VRC.Udon.Common; [ExecuteInEditMode] [UdonBehaviourSyncMode(BehaviourSyncMode.Manual)] public class CameraOverlay : UdonSharpBehaviour { [SerializeField] private Animator _Animator; [SerializeField] private GameObject _OverlayElements; [Space] [SerializeField, Range(0.0f, 2.5f)] private float _AspectRatio = 1.7777777777777777777777777777777777777f; [UdonSynced] private bool _OverlayElementsEnabled = false; [UdonSynced] private bool _FadeOutAnimation = false; private Camera _Camera = null; private const float NEAR_PLANE_OFFSET = 0.05f; void Update() { if (transform.parent != null) { if (_Camera != null) { _UpdateCameraSettings(); return; } Camera ParentCamera = GetComponentInParent(); if (ParentCamera) { _Camera = ParentCamera; transform.localRotation = Quaternion.identity; _UpdateCameraSettings(); } else { _Camera = null; } } } public override void OnDeserialization(DeserializationResult Result) { _EnableOverlayElements_Synced(); _PlayFadeOutAnimation_Synced(); base.OnDeserialization(Result); } public void EnableOverlayElements(bool Enable) { _OverlayElementsEnabled = Enable; _EnableOverlayElements_Synced(); _FadeOutAnimation = false; _PlayFadeOutAnimation_Synced(); RequestSerialization(); } private void _EnableOverlayElements_Synced() { _OverlayElements.SetActive(_OverlayElementsEnabled); } public void PlayFadeOutAnimation() { _FadeOutAnimation = true; _PlayFadeOutAnimation_Synced(); RequestSerialization(); } private void _PlayFadeOutAnimation_Synced() { if (_Animator) { _Animator.SetBool("Fade Out", _FadeOutAnimation); } } private void _UpdateCameraSettings() { Vector3 Position = Vector3.zero; Position.z = _Camera.nearClipPlane + NEAR_PLANE_OFFSET; transform.localPosition = Position; Vector3 Scale = Vector3.one; Scale.y = 2.0f * Position.z * Mathf.Tan(_Camera.fieldOfView * 0.5f * Mathf.Deg2Rad); Scale.x = Scale.y * _AspectRatio; transform.localScale = Scale; } }