using UnityEngine; using System.Collections; namespace IndianOceanAssets.Engine2_5D { /// /// 场景交互点 —— 玩家走到指定物体附近,按 Q 触发过场。 /// 触发后主角的光圈逐渐扩大,最终点亮整个场景(PPT式过渡)。 /// /// 挂载位置:场景中的交互物件(如祭坛、机关、特殊NPC等) /// 需要:物体上有 Collider + 勾选 IsTrigger /// 玩家需要 Tag = "Player" /// public class SceneInteraction : MonoBehaviour { [Header("交互设置")] [SerializeField] private KeyCode interactKey = KeyCode.Q; [Tooltip("玩家进入此范围才能交互")] [SerializeField] private float interactionRadius = 3f; [Header("过场参数")] [Tooltip("光圈扩大的持续时间(秒),类似PPT过场")] [SerializeField] private float transitionDuration = 5f; [Tooltip("最终光圈半径(要覆盖整个场景的话设大一点)")] [SerializeField] private float finalLightRadius = 60f; [Tooltip("最终全局最小亮度(0.6=全场景可见但偏暗, 1.0=全亮)")] [SerializeField, Range(0f, 1f)] private float finalMinBrightness = 0.7f; [Header("引用")] [Tooltip("玩家的 LightSource 组件(必须已挂载)")] [SerializeField] private LightSource playerLightSource; [Tooltip("交互提示 UI(可选,玩家靠近时显示)")] [SerializeField] private GameObject interactionPrompt; [Header("音效(可选)")] [SerializeField] private AudioSource interactionSFX; // 状态 private bool _triggered = false; private bool _playerInRange = false; private Transform _player; private void Start() { // 自动查找玩家 GameObject playerObj = GameObject.FindGameObjectWithTag("Player"); if (playerObj != null) { _player = playerObj.transform; if (playerLightSource == null) playerLightSource = playerObj.GetComponent(); } if (interactionPrompt != null) interactionPrompt.SetActive(false); } private void Update() { if (_triggered) return; // 检测玩家是否在范围内 if (_player != null) { float dist = Vector3.Distance(transform.position, _player.position); _playerInRange = dist <= interactionRadius; } // 显示/隐藏交互提示 if (interactionPrompt != null) interactionPrompt.SetActive(_playerInRange); // 检测 Q 键 if (_playerInRange && Input.GetKeyDown(interactKey)) { StartCoroutine(ExpandLightTransition()); } } /// /// 过场协程:光圈逐渐扩大 + 全局亮度提升 /// private IEnumerator ExpandLightTransition() { _triggered = true; // 隐藏交互提示 if (interactionPrompt != null) interactionPrompt.SetActive(false); // 播放音效 if (interactionSFX != null) interactionSFX.Play(); // 记录初始值 float startRadius = playerLightSource != null ? playerLightSource.Radius : 5f; float startBrightness = LightMaskSystem.Instance != null ? 0f : 0f; float elapsed = 0f; // 过程:平滑插值扩大 while (elapsed < transitionDuration) { elapsed += Time.deltaTime; float t = elapsed / transitionDuration; // SmoothStep 插值(开始和结束都柔和) float smoothT = t * t * (3f - 2f * t); // 扩大玩家光圈半径 if (playerLightSource != null) playerLightSource.SetRadius(Mathf.Lerp(startRadius, finalLightRadius, smoothT)); // 提升全局最小亮度(让黑暗区域也逐渐可见) if (LightMaskSystem.Instance != null) LightMaskSystem.Instance.SetMinBrightness(Mathf.Lerp(startBrightness, finalMinBrightness, smoothT)); yield return null; } // 确保最终值 if (playerLightSource != null) playerLightSource.SetRadius(finalLightRadius); if (LightMaskSystem.Instance != null) LightMaskSystem.Instance.SetMinBrightness(finalMinBrightness); Debug.Log("[SceneInteraction] 过场完成,场景已全部点亮"); } // ===== 编辑器可视化 ===== private void OnDrawGizmosSelected() { Gizmos.color = new Color(0f, 1f, 0f, 0.3f); Gizmos.DrawWireSphere(transform.position, interactionRadius); } } }