143 lines
5.0 KiB
C#
143 lines
5.0 KiB
C#
using UnityEngine;
|
||
using System.Collections;
|
||
|
||
namespace IndianOceanAssets.Engine2_5D
|
||
{
|
||
/// <summary>
|
||
/// 场景交互点 —— 玩家走到指定物体附近,按 Q 触发过场。
|
||
/// 触发后主角的光圈逐渐扩大,最终点亮整个场景(PPT式过渡)。
|
||
///
|
||
/// 挂载位置:场景中的交互物件(如祭坛、机关、特殊NPC等)
|
||
/// 需要:物体上有 Collider + 勾选 IsTrigger
|
||
/// 玩家需要 Tag = "Player"
|
||
/// </summary>
|
||
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<LightSource>();
|
||
}
|
||
|
||
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());
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 过场协程:光圈逐渐扩大 + 全局亮度提升
|
||
/// </summary>
|
||
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);
|
||
}
|
||
}
|
||
}
|