Files

122 lines
4.7 KiB
C#
Raw Permalink Normal View History

2026-07-18 03:16:20 -04:00
using Cielonos.MainGame.Characters;
using UnityEngine;
namespace Cielonos.MainGame.Effects.Feedback
{
/// <summary>
/// 反馈用向量转换工具。
/// 统一处理“攻击方向”“摄像机本地方向”“反馈振幅”等常见转换,避免各个武器和角色重复实现。
/// </summary>
public static class FeedbackVectorUtility
{
private const float DirectionEpsilon = 0.0001f;
/// <summary>
/// 获取攻击打向目标的世界方向。
/// 对于 Projectile优先使用真实移动速度方向对于 NormalArea使用攻击者指向目标的方向。
/// </summary>
public static Vector3 GetAttackDirection(AttackAreaBase attackArea, CharacterBase target)
{
if (attackArea == null)
{
return Vector3.forward;
}
if (attackArea is Projectile)
{
return GetProjectileDirection(attackArea);
}
if (attackArea is NormalArea && attackArea.creator != null && target != null)
{
return NormalizeOrFallback(
target.CenterPoint.position - attackArea.creator.CenterPoint.position,
attackArea.topParent.forward);
}
if (attackArea.creator != null && target != null)
{
return NormalizeOrFallback(
target.CenterPoint.position - attackArea.creator.CenterPoint.position,
attackArea.topParent.forward);
}
return NormalizeOrFallback(attackArea.topParent.forward, Vector3.forward);
}
/// <summary>
/// 将世界方向转换为摄像机本地方向。
/// 摄像机不存在时返回标准化世界方向,保证调用端仍能获得稳定结果。
/// </summary>
public static Vector3 WorldDirectionToCameraLocal(Vector3 worldDirection, Camera camera)
{
Vector3 normalizedDirection = NormalizeOrFallback(worldDirection, Vector3.forward);
return camera != null
? camera.transform.InverseTransformDirection(normalizedDirection).normalized
: normalizedDirection;
}
/// <summary>
/// 获取攻击方向对应的摄像机本地方向。
/// 语义为“攻击从来源打向目标”,适合玩家受击、受击后处理、方向性摄像机反馈等场景。
/// </summary>
public static Vector3 GetCameraLocalAttackDirection(AttackAreaBase attackArea, CharacterBase target, Camera camera)
{
Vector3 attackDirection = GetAttackDirection(attackArea, target);
return WorldDirectionToCameraLocal(attackDirection, camera);
}
/// <summary>
/// 根据方向和强度生成摄像机反馈振幅。
/// </summary>
public static Vector3 DirectionToAmplitude(Vector3 direction, float strength)
{
return NormalizeOrFallback(direction, Vector3.forward) * Mathf.Max(0f, strength);
}
/// <summary>
/// 根据命中点在屏幕中的横向位置生成振幅。
/// 适合远程命中确认等“屏幕位置比物理飞行方向更重要”的反馈。
/// </summary>
public static Vector3 ScreenHitPositionToAmplitude(
Vector3 hitPosition,
Camera camera,
float horizontalStrength,
float verticalKick,
float depthKick)
{
if (camera == null)
{
return new Vector3(0f, verticalKick, depthKick);
}
Vector3 viewportPosition = camera.WorldToViewportPoint(hitPosition);
float screenX = viewportPosition.z >= 0f
? Mathf.Clamp((viewportPosition.x - 0.5f) * 2f, -1f, 1f)
: 0f;
return new Vector3(screenX * horizontalStrength, verticalKick, depthKick);
}
private static Vector3 GetProjectileDirection(AttackAreaBase attackArea)
{
if (attackArea.moveSm != null && attackArea.moveSm.unscaledVelocity.sqrMagnitude > DirectionEpsilon)
{
return attackArea.moveSm.unscaledVelocity.normalized;
}
return NormalizeOrFallback(attackArea.topParent.forward, Vector3.forward);
}
private static Vector3 NormalizeOrFallback(Vector3 direction, Vector3 fallback)
{
if (direction.sqrMagnitude > DirectionEpsilon)
{
return direction.normalized;
}
return fallback.sqrMagnitude > DirectionEpsilon ? fallback.normalized : Vector3.forward;
}
}
}