Files
Cielonos/Assets/Scripts/MainGame/Effects/Feedbacks/Utilities/FeedbackVectorUtility.cs
SoulliesOfficial 39b43680a9 爆更
2026-07-18 03:16:20 -04:00

122 lines
4.7 KiB
C#
Raw Permalink 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 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;
}
}
}