Files
Gen_Hack-and-Slash-Roguelite/Client/Assets/Scripts/EventWorkClass/Event_PlayAudio.cs

162 lines
6.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Managers;
using Newtonsoft.Json;
using UnityEngine;
namespace EventWorkClass
{
/// <summary>
/// 音频播放事件的配置类。
/// 通过JSON字符串进行初始化。
/// </summary>
public class AudioEventConfig
{
[Tooltip("要播放的音频定义名,通过 AudioManager 获取 AudioClip。")]
public string audioClipName;
[Tooltip("播放音量。0.0 到 1.0。")]
[Range(0f, 1f)]
public float volume = 1.0f;
[Tooltip("是否循环播放。")]
public bool loop = false;
[Tooltip("空间混合。0.0 为完全2D1.0 为完全3D。")]
[Range(0f, 1f)]
public float spatialBlend = 0.0f; // 默认为2D音效
[Tooltip("如果存在发起者是否将音频播放到发起者initiator的 AudioSource 上。")]
public bool attachToInitiator = true;
[Tooltip("播放前的延迟秒数。")]
public float delay = 0.0f;
[Tooltip("如果是非循环播放且是临时创建的 AudioSource是否在播放结束后自动销毁。")]
public bool destroyAfterPlay = true;
/// <summary>
/// 验证配置是否有效。
/// </summary>
public bool IsValid()
{
return !string.IsNullOrEmpty(audioClipName);
}
}
/// <summary>
/// 实现一个音频播放事件。
/// 配置通过JSON字符串传入可指定音频名、音量、循环、空间混合、是否依附于发起者等。
/// </summary>
public class Event_PlayAudio : EventWorkClassBase
{
private AudioEventConfig _config;
private bool _isInitialized = false;
/// <summary>
/// 初始化音频播放事件解析JSON配置。
/// </summary>
/// <param name="value">包含音频配置的JSON字符串。</param>
public override void Init(string value)
{
_isInitialized = false;
if (string.IsNullOrEmpty(value))
{
Debug.LogError("EventPlayAudio 初始化错误:配置 JSON 值为 null 或空。跳过初始化。");
return;
}
try
{
// 使用 Newtonsoft.Json 进行反序列化
_config = JsonConvert.DeserializeObject<AudioEventConfig>(value);
if (_config == null || !_config.IsValid())
{
Debug.LogError("EventPlayAudio 初始化错误:反序列化的配置无效或为空。音频剪辑名称可能缺失。跳过初始化。");
}
else
{
_isInitialized = true;
}
}
catch (System.Exception ex) // 可以更具体地捕获 Newtonsoft.Json.JsonException
{
Debug.LogError($"EventPlayAudio 初始化错误:使用 Newtonsoft.Json 解析 JSON 配置失败:{ex.Message}\nJSON: {value}");
}
}
/// <summary>
/// 运行音频播放事件。
/// </summary>
/// <param name="dimensionID">维度ID此事件中暂未使用保留扩展性。</param>
/// <param name="initiator">事件发起者实体可能包含一个AudioSource。</param>
public override void Run(string dimensionID, Entity.Entity initiator = null)
{
if (!_isInitialized)
{
Debug.LogError("EventPlayAudio 运行错误:事件未初始化或配置无效。跳过音频播放。");
return;
}
// 获取音频片段
var audioClip = AudioManager.Instance.GetAudioClip(_config.audioClipName);
if (!audioClip)
{
Debug.LogError($"EventPlayAudio 运行错误AudioManager 中未找到音频剪辑 '{_config.audioClipName}'。跳过播放。");
return;
}
AudioSource audioSourceToUse = null;
var isTemporaryAudioSource = false;
// 尝试使用发起者的AudioSource
if (_config.attachToInitiator && initiator != null && initiator.Audio != null)
{
audioSourceToUse = initiator.Audio;
}
else
{
// 如果没有发起者AudioSource或不依附于发起者则创建临时的GameObject和AudioSource
var tempAudioGO = new GameObject($"TempAudio__{_config.audioClipName}");
audioSourceToUse = tempAudioGO.AddComponent<AudioSource>();
isTemporaryAudioSource = true;
if (_config.spatialBlend > 0f)
{
if (initiator != null)
{
tempAudioGO.transform.position = initiator.transform.position;
}
else
{
tempAudioGO.transform.position = Vector3.zero; // 默认位置
}
}
// 如果 spatialBlend 为 0则无需设置位置它将保持默认的 Vector3.zero。
}
// 配置AudioSource参数
audioSourceToUse.clip = audioClip;
audioSourceToUse.volume = _config.volume;
audioSourceToUse.loop = _config.loop;
audioSourceToUse.spatialBlend = _config.spatialBlend;
audioSourceToUse.playOnAwake = false; // 由Run方法显式控制播放
// 播放音频
if (_config.delay > 0)
{
audioSourceToUse.PlayDelayed(_config.delay);
}
else
{
audioSourceToUse.Play();
}
// 如果是临时AudioSource且不循环播放且配置为播放后销毁则在播放结束后自动销毁
if (isTemporaryAudioSource && !_config.loop && _config.destroyAfterPlay)
{
// 计算销毁时间:延迟 + 音频长度
var destroyTime = _config.delay + audioClip.length;
Object.Destroy(audioSourceToUse.gameObject, destroyTime);
}
// 如果是循环播放的临时AudioSource不自动销毁需要外部机制停止/销毁
else if (isTemporaryAudioSource && _config.loop)
{
Debug.LogWarning($"EventPlayAudio为 '{_config.audioClipName}' 创建了循环临时 AudioSource。它将不会被自动销毁。需要外部管理来停止和销毁它。");
}
}
}
}