Files
vampire-like/Assets/GameMain/Scripts/Runtime/CustomComponent/Simulation/Presentation/SimulationWorld.HitPresentation.cs
T
2026-09-18 21:43:22 +08:00

138 lines
4.5 KiB
C#

using SepCore.Event;
using SepCore.Entity;
using SepCore.AsyncTask;
using Cysharp.Threading.Tasks;
using GameFramework.Event;
using UnityEngine;
namespace SepCore.Simulation
{
public sealed partial class SimulationWorld
{
[Header("投射物命中表现")]
[Tooltip("是否监听投射物命中表现事件。")]
[SerializeField]
private bool _projectileHitPresentationEnabled = true;
[Tooltip("是否播放投射物命中标记。")]
[SerializeField]
private bool _projectileHitMarkerEnabled = true;
#pragma warning disable CS0414
[Tooltip("命中标记尺寸。")][SerializeField] private float _projectileHitMarkerSize = 0.2f;
[Tooltip("命中标记在目标上的高度偏移。")]
[SerializeField]
private float _projectileHitMarkerYOffset = 1.2f;
[Tooltip("命中标记持续时间。")]
[SerializeField]
private float _projectileHitMarkerDuration = 0.15f;
#pragma warning restore CS0414
[Tooltip("命中标记颜色。")][SerializeField] private Color _projectileHitMarkerColor = new(1f, 0f, 0f, 0.95f);
[Tooltip("是否播放投射物命中特效实体。")]
[SerializeField]
private bool _projectileHitEffectEnabled;
[Tooltip("投射物命中特效实体类型 Id(<=0 表示不启用)。")]
[SerializeField]
private int _projectileHitEffectTypeId;
private sealed class HitPresentation
{
private readonly SimulationWorld _world;
private HandgunHitMarkerAttackEffect _projectileHitMarkerEffect;
private bool _isProjectileHitEventSubscribed;
public HitPresentation(SimulationWorld world)
{
_world = world;
}
public void OnStart()
{
if (_world == null || !_world._projectileHitPresentationEnabled)
{
return;
}
var eventComponent = GameEntry.Event;
if (eventComponent == null)
{
return;
}
eventComponent.Subscribe(ProjectileHitPresentationEventArgs.EventId, OnProjectileHitPresentationEvent);
_isProjectileHitEventSubscribed = true;
}
public void OnDestroy()
{
if (!_isProjectileHitEventSubscribed)
{
return;
}
var eventComponent = GameEntry.Event;
if (eventComponent != null)
{
eventComponent.Unsubscribe(ProjectileHitPresentationEventArgs.EventId,
OnProjectileHitPresentationEvent);
}
_isProjectileHitEventSubscribed = false;
}
private void OnProjectileHitPresentationEvent(object sender, GameEventArgs e)
{
if (!_isProjectileHitEventSubscribed || _world == null ||
e is not ProjectileHitPresentationEventArgs args)
{
return;
}
if (args.ShowHitMarker && _world._projectileHitMarkerEnabled)
{
PlayHitMarker(args);
}
if (args.ShowHitEffect && _world._projectileHitEffectEnabled)
{
PlayHitEffect(args);
}
}
private void PlayHitMarker(ProjectileHitPresentationEventArgs args)
{
// Projectile hit markers were reusing the handgun marker effect and were
// visually indistinguishable from handgun lock/hit feedback.
}
private void PlayHitEffect(ProjectileHitPresentationEventArgs args)
{
int effectTypeId = args.EffectEntityTypeId > 0
? args.EffectEntityTypeId
: _world._projectileHitEffectTypeId;
if (effectTypeId <= 0)
{
return;
}
var entityComponent = GameEntry.Entity;
if (entityComponent == null)
{
return;
}
EffectData effectData = new EffectData(entityComponent.NextId(), effectTypeId)
{
Position = args.HitPosition
};
entityComponent.ShowEffectAsync(effectData).Forget();
}
}
}
}