using UnityEngine; using Unity.VRTemplate; [RequireComponent(typeof(Collider))] public class ArtWorkIntroController : MonoBehaviour { [SerializeField] private AudioClip introClip; [SerializeField, Tooltip("对应的艺术品,例如 Painting7")] private GameObject artwork; [SerializeField, Tooltip("解说时显示的信息卡对象")] private GameObject infoCard; [SerializeField, Tooltip("与解说音频同名的作品信息卡图片")] private Texture infoCardTexture; [SerializeField, Tooltip("可用的信息卡图片,运行时按解说音频名称自动匹配")] private Texture[] infoCardTextures; private int collidersInside; private bool isFacing; private CalloutGazeController gazeController; private AudioManager audioManager; private bool audioManagerReady; private MaterialPropertyBlock infoCardProperties; private static readonly int BaseMapId = Shader.PropertyToID("_BaseMap"); private static readonly int MainTexId = Shader.PropertyToID("_MainTex"); private void Awake() { if (artwork != null) { gazeController = artwork.GetComponent(); } ConfigureInfoCard(); SetInfoCardVisible(false); } private void OnEnable() { if (audioManagerReady) { audioManager.NarrationEnabledChanged += OnNarrationEnabledChanged; audioManager.ActiveIntroChanged += OnActiveIntroChanged; } if (gazeController == null) { return; } gazeController.FacingEnteredEvent.AddListener(OnFacingEntered); gazeController.FacingExitedEvent.AddListener(OnFacingExited); } private void Start() { audioManager = AudioManager.Instance; audioManagerReady = true; audioManager.NarrationEnabledChanged += OnNarrationEnabledChanged; audioManager.ActiveIntroChanged += OnActiveIntroChanged; UpdatePlayback(); } private void OnDisable() { if (audioManager != null) { audioManager.NarrationEnabledChanged -= OnNarrationEnabledChanged; audioManager.ActiveIntroChanged -= OnActiveIntroChanged; audioManager.PauseArtWorkIntro(introClip); } collidersInside = 0; isFacing = false; if (gazeController != null) { gazeController.FacingEnteredEvent.RemoveListener(OnFacingEntered); gazeController.FacingExitedEvent.RemoveListener(OnFacingExited); } SetInfoCardVisible(false); } private void OnTriggerEnter(Collider other) { if (!isActiveAndEnabled || !other.CompareTag("Player")) { return; } collidersInside++; UpdatePlayback(); } private void OnTriggerExit(Collider other) { if (!isActiveAndEnabled || !other.CompareTag("Player")) { return; } collidersInside = Mathf.Max(0, collidersInside - 1); UpdatePlayback(); } private void OnFacingEntered() { isFacing = true; UpdatePlayback(); } private void OnFacingExited() { isFacing = false; UpdatePlayback(); } private void OnNarrationEnabledChanged(bool isEnabled) { UpdatePlayback(); } private void OnActiveIntroChanged() { UpdateInfoCard(); } private void UpdatePlayback() { if (!audioManagerReady) { SetInfoCardVisible(false); return; } bool shouldPlay = audioManager.NarrationEnabled && collidersInside > 0 && isFacing; if (shouldPlay) { audioManager.PlayArtWorkIntro(introClip); } else { audioManager.PauseArtWorkIntro(introClip); } UpdateInfoCard(); } private void UpdateInfoCard() { bool shouldShow = audioManagerReady && audioManager.NarrationEnabled && collidersInside > 0 && isFacing && audioManager.CurrentIntroClip == introClip; SetInfoCardVisible(shouldShow); } private void ConfigureInfoCard() { Texture texture = FindMatchingInfoCardTexture(); if (infoCard == null || texture == null) { return; } Renderer cardRenderer = infoCard.GetComponent(); if (cardRenderer == null) { return; } infoCardProperties = new MaterialPropertyBlock(); cardRenderer.GetPropertyBlock(infoCardProperties); infoCardProperties.SetTexture(BaseMapId, texture); infoCardProperties.SetTexture(MainTexId, texture); cardRenderer.SetPropertyBlock(infoCardProperties); } private Texture FindMatchingInfoCardTexture() { if (introClip != null && infoCardTextures != null) { foreach (Texture texture in infoCardTextures) { if (texture != null && texture.name == introClip.name) { return texture; } } } return infoCardTexture; } private void SetInfoCardVisible(bool isVisible) { if (infoCard != null && infoCard.activeSelf != isVisible) { infoCard.SetActive(isVisible); } } private void Reset() { GetComponent().isTrigger = true; } }