Files
Cielonos/Assets/Scripts/MainGame/AttackArea/Collection/NormalArea.cs
SoulliesOfficial 649b7a5ddc 更新
2026-05-23 08:27:50 -04:00

110 lines
4.5 KiB
C#

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)
{
return;
}
CharacterBase targetCharacter = characterCollider.GetComponentInParent<CharacterBase>();
if (!IsValidTarget(targetCharacter)) return;
if (hitSm.checkedObjects.Contains(targetCharacter.gameObject))
{
return;
}
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;
}
}
}