MusicBeat

This commit is contained in:
SoulliesOfficial
2026-05-26 00:21:27 -04:00
parent 649b7a5ddc
commit b5cb6152ff
663 changed files with 534461 additions and 587 deletions

View File

@@ -0,0 +1,154 @@
using System.Collections.Generic;
using Cielonos.MainGame.Characters;
using SLSUtilities.General;
using SoftCircuits.Collections;
using UnityEngine;
namespace Cielonos.MainGame.Inventory
{
/// <summary>
/// 光环子模块。持续捕获指定半径内的角色,并通过 Enter / Stay / Exit 事件通知订阅方。
/// 不使用 Data ScriptableObject由道具在代码中直接构造。
/// </summary>
public class AuraSubmodule : SubmoduleBase<ItemBase>
{
/// <summary>
/// 当前处于光环内的角色集合。
/// </summary>
public HashSet<CharacterBase> charactersInAura = new HashSet<CharacterBase>();
/// <summary>
/// 其他角色进入光环时触发,参数为进入的角色。
/// </summary>
public OrderedDictionary<string, PrioritizedAction<CharacterBase>> onOtherEnterAura = new();
/// <summary>
/// 其他角色持续处于光环内时触发(按 stayInterval 间隔),参数为在光环内的角色。
/// </summary>
public OrderedDictionary<string, PrioritizedAction<CharacterBase>> onOtherStayAura = new();
/// <summary>
/// 其他角色离开光环时触发,参数为离开的角色。
/// </summary>
public OrderedDictionary<string, PrioritizedAction<CharacterBase>> onOtherExitAura = new();
/// <summary>
/// 光环半径。
/// </summary>
public float auraRadius;
/// <summary>
/// Stay 计时器,到达 stayInterval 后对所有在光环内的角色触发 onOtherStayAura。
/// </summary>
public Timer stayTimer;
/// <summary>
/// 物理检测的 LayerMask。
/// </summary>
private readonly int _detectionLayerMask;
private const int MaxDetectionCount = 32;
private readonly Collider[] _overlapBuffer = new Collider[MaxDetectionCount];
/// <summary>
/// 用于比较前后帧角色集合的临时缓冲。
/// </summary>
private readonly HashSet<CharacterBase> _currentFrameCharacters = new HashSet<CharacterBase>();
/// <summary>
/// 构造光环子模块。
/// </summary>
/// <param name="owner">所属道具。</param>
/// <param name="auraRadius">光环半径。</param>
/// <param name="stayInterval">Stay 事件触发间隔(秒),默认 0.5 秒。</param>
public AuraSubmodule(ItemBase owner, float auraRadius, float stayInterval = 0.5f) : base(owner)
{
this.auraRadius = auraRadius;
stayTimer = new Timer(stayInterval, isInfinite: true);
stayTimer.onComplete.Add(new PrioritizedAction(OnStayTimerComplete));
_detectionLayerMask = LayerMask.GetMask("HurtBox");
}
/// <summary>
/// 每帧调用,驱动物理检测和事件派发。
/// </summary>
public void Update(float deltaTime)
{
DetectCharacters();
stayTimer.Update(deltaTime);
}
/// <summary>
/// 清理所有追踪状态,对仍在光环内的角色触发 Exit 事件。
/// </summary>
public void Dispose()
{
foreach (var character in charactersInAura)
{
if (character != null)
{
onOtherExitAura.Invoke(character);
}
}
charactersInAura.Clear();
}
/// <summary>
/// 执行球形物理检测,比较前后帧角色集合,触发 Enter / Exit 事件。
/// </summary>
private void DetectCharacters()
{
_currentFrameCharacters.Clear();
Vector3 center = owner.player.transform.position;
int hitCount = Physics.OverlapSphereNonAlloc(center, auraRadius, _overlapBuffer, _detectionLayerMask);
for (int i = 0; i < hitCount; i++)
{
CharacterBase character = _overlapBuffer[i].GetComponentInParent<CharacterBase>();
if (character == null || character == owner.player) continue;
_currentFrameCharacters.Add(character);
}
// 检测新进入光环的角色
foreach (var character in _currentFrameCharacters)
{
if (charactersInAura.Add(character))
{
onOtherEnterAura.Invoke(character);
}
}
// 检测离开光环的角色(从旧集合中移除不在当前帧的角色)
charactersInAura.RemoveWhere(character =>
{
if (_currentFrameCharacters.Contains(character)) return false;
if (character != null)
{
onOtherExitAura.Invoke(character);
}
return true;
});
}
/// <summary>
/// Stay 计时器到期时,对所有在光环内的角色触发 onOtherStayAura。
/// </summary>
private void OnStayTimerComplete()
{
foreach (var character in charactersInAura)
{
if (character != null)
{
onOtherStayAura.Invoke(character);
}
}
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 84bc61c526c4a824a9267b1a5c2e3ff4