Files
Cielonos/Assets/Scripts/MainGame/AttackArea/Collection/NormalArea.cs
SoulliesOfficial 6d7ebc5825 Passion & UI
2026-06-12 17:11:39 -04:00

131 lines
5.6 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 Cielonos.MainGame.Characters;
using Cielonos.MainGame.Inventory;
using SLSUtilities.General;
using UnityEngine;
namespace Cielonos.MainGame
{
public partial class NormalArea : AttackAreaBase
{
public override T Initialize<T>(CharacterBase creator, ItemBase itemSource, params Fraction[] targetFractions)
{
T area = base.Initialize<T>(creator, itemSource, targetFractions);
topParent.transform.localScale *= creator.attributeSm[CharacterAttribute.AttackRangeMultiplier];
return area;
}
private void OnTriggerStay(Collider other)
{
HitCharacter(other, default);
}
public override void HitCharacter(Collider characterCollider, Vector3 hitPosition)
{
// 既不在伤害阶段也不在反应窗口,直接跳过
if (!isEnabling && !isReactionActive)
{
return;
}
CharacterBase targetCharacter = characterCollider.GetComponentInParent<CharacterBase>();
if (!IsValidTarget(targetCharacter)) return;
// 已在 grace window 期间成功反应的目标不再处理
if (reactedTargets.Contains(targetCharacter.gameObject))
{
return;
}
if (hitSm.checkedObjects.Contains(targetCharacter.gameObject))
{
return;
}
// 仅在反应窗口内enable 阶段之前或之后),只做反应检测
if (!isEnabling && isReactionActive)
{
HitOnTarget(characterCollider, areaCollider.ClosestPoint(targetCharacter.CenterPoint.position),
out Attack.Result graceResult, onlyCheckReaction: true);
if (graceResult.isBlocked || graceResult.isDodged)
{
reactedTargets.Add(targetCharacter.gameObject);
hitSm.AddCheckedObject(targetCharacter.gameObject);
Debug.Log($"[NormalArea] Target {targetCharacter.name} successfully reacted during grace window. Blocked: {graceResult.isBlocked}, Dodged: {graceResult.isDodged}");
}
return;
}
// 正常 enable 阶段:造成伤害
hitSm.AddCheckedObject(targetCharacter.gameObject);
HitOnTarget(characterCollider, areaCollider.ClosestPoint(targetCharacter.CenterPoint.position), out _);
}
}
public partial class NormalArea
{
protected override GameObject GenerateHitEffect(CharacterBase target, Collider hitCollider, Vector3 hitPosition)
{
GameObject hitEffect = base.GenerateHitEffect(target, hitCollider, hitPosition);
if(hitEffect == null) return null;
Vector3 hitEffectDirection = GetHitEffectDirection(hitCollider.ClosestPoint(transform.position));
hitEffect.transform.rotation = Quaternion.LookRotation(hitEffectDirection);
return hitEffect;
}
}
public partial class NormalArea
{
/// <summary>
/// 计算命中特效应朝向的方向 (Z轴)。
/// 这个方向是刀光在命中点的旋转切线方向。
/// </summary>
/// <param name="hitPosition">世界空间中的命中点</param>
/// <returns>一个标准化的方向向量 (world space)</returns>
private Vector3 GetHitEffectDirection(Vector3 hitPosition)
{
// 1. 获取刀光旋转的中心点
// (假设 creator.flexibleCenterPoint.position 是旋转中心)
Vector3 rotationCenter = creator.CenterPoint.position;
// 2. 获取刀光旋转的法线 (旋转轴)
// 根据描述, 这是刀光 prefab 的 Y 轴正方向
Vector3 rotationNormal = transform.up; // 刀光的 local Y 轴 (in world space)
// 3. 计算从中心点到命中点的半径向量
Vector3 radiusVector = hitPosition - rotationCenter;
// 4. (重要) 将半径向量投影到旋转平面上.
// 这是为了确保我们得到一个与旋转轴垂直的向量,
// 防止 hitPosition 轻微偏离平面导致计算错误.
// 你的代码中 hitDirection.y = 0 是在错误的平面上投影.
Vector3 radiusOnPlane = Vector3.ProjectOnPlane(radiusVector, rotationNormal);
// 5. 计算切线.
// 需求: "Y轴正方向顺时针旋转"
// 在 Unity (左手坐标系) 中:
// - 轴 (Normal) = Y (0, 1, 0)
// - 半径 (Radius) = X (1, 0, 0)
// - 顺时针旋转 (Clockwise) 是从 +X 转向 -Z.
//
// - Vector3.Cross(rotationNormal, radiusOnPlane)
// = Cross((0,1,0), (1,0,0)) = (0, 0, -1) (-> 指向 -Z)
// - 这正是我们需要的顺时针切线方向.
Vector3 tangentDirection = Vector3.Cross(rotationNormal, radiusOnPlane);
// 6. (安全检查) 处理命中点在中心的情况
// 如果命中点非常接近旋转中心, 半径为0, 叉乘结果也为0.
// .normalized 会返回 NaN, 导致 LookRotation 失败.
if (tangentDirection.sqrMagnitude < 0.0001f)
{
// 此时没有明确的 "切线".
// 我们可以返回刀光的 "forward" (Z轴) 或 "right" (X轴) 作为备用.
// 让我们使用刀光的 X 轴 (即刀光"刀刃"的初始方向).
return transform.right;
}
// 7. 返回标准化的切线方向
return tangentDirection.normalized;
}
}
}