Files
Cielonos/Assets/Scripts/MainGame/Characters/Automata/Subcontrollers/AutomataLandMovementSubcontroller.cs

177 lines
5.8 KiB
C#
Raw Normal View History

2026-02-13 09:22:11 -05:00
using SLSUtilities.General;
2025-11-25 08:19:33 -05:00
using UnityEngine;
using UnityEngine.AI;
namespace Cielonos.MainGame.Characters
{
2026-02-13 09:22:11 -05:00
public partial class AutomataLandMovementSubcontroller : LandMovementSubcontroller
2025-11-25 08:19:33 -05:00
{
2026-05-10 11:47:55 -04:00
public NavMeshAgent navMeshAgent => (owner as Automata)!.behaviorSc.navMeshAgent;
2026-03-20 12:07:44 -04:00
public LerpFloat moveSpeedX;
2025-11-25 08:19:33 -05:00
public LerpFloat moveSpeedZ;
public override void Initialize()
{
base.Initialize();
2026-01-03 18:19:39 -05:00
navMeshAgent.isStopped = true;
2026-03-20 12:07:44 -04:00
moveSpeedX = new LerpFloat(0f, 5f);
2025-11-25 08:19:33 -05:00
moveSpeedZ = new LerpFloat(0f, 5f);
}
2025-12-08 05:27:53 -05:00
private Vector3 lastDirection;
2026-02-13 09:22:11 -05:00
protected override void Update()
{
base.Update(); // 更新 isOnGround
HandleNavMeshState();
}
2026-01-12 03:22:16 -05:00
protected override void OnAnimatorMove()
2025-11-25 08:19:33 -05:00
{
2026-03-20 12:07:44 -04:00
if (owner.selfTimeSm.DeltaTime == 0 || owner.statusSm.isDead)
2025-11-25 08:19:33 -05:00
{
return;
}
2026-02-13 09:22:11 -05:00
if (navMeshAgent != null && navMeshAgent.enabled)
2025-11-25 08:19:33 -05:00
{
2026-03-20 12:07:44 -04:00
if (!is8WayMovement)
2025-11-25 08:19:33 -05:00
{
2026-03-20 12:07:44 -04:00
if (!navMeshAgent.isStopped)
{
float distanceVelocity = navMeshAgent.velocity.magnitude;
float angularVelocity = Vector3.Angle(lastDirection, transform.forward) / owner.selfTimeSm.DeltaTime;
moveSpeedZ.targetValue = distanceVelocity + (angularVelocity * 0.1f);
}
else
{
moveSpeedZ.targetValue = 0f;
}
moveSpeedZ.Update(0.2f, 1);
animator.SetFloat("MoveSpeedZ", moveSpeedZ.currentValue);
}
2026-01-03 18:19:39 -05:00
else
{
2026-03-20 12:07:44 -04:00
if (!navMeshAgent.isStopped)
{
Vector3 distanceVelocity = navMeshAgent.velocity;
float xValue = Vector3.Dot(distanceVelocity, transform.right);
float zValue = Vector3.Dot(distanceVelocity, transform.forward);
moveSpeedX.targetValue = xValue;
moveSpeedZ.targetValue = zValue;
}
else
{
moveSpeedX.targetValue = 0f;
moveSpeedZ.targetValue = 0f;
}
moveSpeedX.Update(0.2f, 1);
moveSpeedZ.Update(0.2f, 1);
animator.SetFloat("MoveSpeedX", moveSpeedX.currentValue);
animator.SetFloat("MoveSpeedZ", moveSpeedZ.currentValue);
2026-01-03 18:19:39 -05:00
}
2025-11-25 08:19:33 -05:00
}
base.OnAnimatorMove();
InitiativeMove();
2025-12-08 05:27:53 -05:00
lastDirection = transform.forward;
2025-11-25 08:19:33 -05:00
}
2026-02-13 09:22:11 -05:00
private void HandleNavMeshState()
{
if (navMeshAgent == null) return;
if (stagnantFirstHalf && !isOnGround && finalMovementVelocity.y <0)
{
stagnantFirstHalf = false;
stagnantLastHalf = true;
}
if (stagnantLastHalf && isOnGround)
{
additionalForceSm.additionalForceY.currentValue = 0;
if (!navMeshAgent.enabled)
{
navMeshAgent.enabled = true;
navMeshAgent.Warp(transform.position);
}
stagnantFirstHalf = false;
stagnantLastHalf = false;
}
}
protected override void ApplyGravity()
{
base.ApplyGravity();
}
2025-11-25 08:19:33 -05:00
protected override void InitiativeMove()
{
if (navMeshAgent.enabled)
{
navMeshAgent.Move(finalMovementVelocity);
2026-03-20 12:07:44 -04:00
navMeshAgent.baseOffset += finalMovementVelocity.y;
navMeshAgent.baseOffset = Mathf.Max(navMeshAgent.baseOffset, 0f);
2025-11-25 08:19:33 -05:00
}
else
{
if (owner.collisionSc.useCharacterController)
{
owner.collisionSc.characterController.Move(finalMovementVelocity);
}
else
{
Vector3 startPosition = owner.collisionSc.mainRigidbody.position;
owner.collisionSc.mainRigidbody.MovePosition(startPosition + finalMovementVelocity);
}
}
}
2026-02-13 09:22:11 -05:00
protected override void UpdateFinalMovement()
{
base.UpdateFinalMovement();
}
}
public partial class AutomataLandMovementSubcontroller
{
public bool stagnantFirstHalf;
public bool stagnantLastHalf;
/// <summary>
/// 处理受击位移
/// </summary>
/// <param name="force">力的矢量</param>
/// <param name="isLaunch">是否为“击飞”(无视抗性,重置重力)</param>
/// <param name="stasisDuration">滞空时间(秒)</param>
public void ApplyHitImpact(Vector3 force, bool isLaunch, float stasisDuration = 0f)
{
// 1. 瞬间切断导航
if (isLaunch && navMeshAgent.enabled) navMeshAgent.enabled = false;
// 2. 施加力
// 如果是击飞(Launch),则 ignoreResistance 为 true (不扣除初速度)
if (!stagnantFirstHalf && !stagnantLastHalf)
{
stagnantFirstHalf = true;
}
additionalForceSm.AddForce(force, isLaunch);
// 3. 处理滞空逻辑 (鬼泣式)
if (stasisDuration > 0)
{
jumpVelocity = 0;
gravitationalMovement = Vector3.zero;
}
}
2025-11-25 08:19:33 -05:00
}
}