using System; using DG.Tweening; using SLSUtilities.General; using UnityEngine; using UnityEngine.AI; namespace Cielonos.MainGame.Characters { public partial class LandMovementSubcontroller : MovementSubcontrollerBase { protected AnimationSubcontrollerBase animationSc => owner.animationSc; protected Animator animator => animationSc.animator; protected virtual void OnAnimatorMove() { movementModifier = Vector3.zero; if (owner.animationSc.isDuringRootMotion) { UpdateRootMotionMovement(); } else { UpdateRegularMovement(); } ApplyGravity(); UpdateFinalMovement(); } protected virtual void Update() { isOnGround = groundDetector.DetectGround(); if (owner.movementSc.dodgeIntervalTimer > 0f) { owner.movementSc.dodgeIntervalTimer -= DeltaTime; } } } public partial class LandMovementSubcontroller { /// /// 如果角色当前在空中,强制其落地。 /// public void ForceLanding() { if(isOnGround) return; if (groundDetector.GetGroundPosition(out Vector3 landingPosition)) { jumpVelocity = 0; gravitationalMovement = Vector3.zero; if (owner.collisionSc.useCharacterController) { owner.collisionSc.characterController.enabled = false; owner.transform.position = landingPosition + new Vector3(0, groundDetector.groundedOffset + 0.1f, 0); owner.collisionSc.characterController.enabled = true; } else { owner.collisionSc.mainRigidbody.position = landingPosition + new Vector3(0, groundDetector.groundedOffset + 0.1f, 0); } } } } public partial class LandMovementSubcontroller { void UpdateRootMotionMovement() { Quaternion originalDeltaRotation = animator.deltaRotation; characterTransform.rotation *= originalDeltaRotation; Vector3 originalDeltaPosition = animator.deltaPosition; Vector3 localDeltaPosition = characterTransform.InverseTransformDirection(originalDeltaPosition); Vector3 adjustedLocalDeltaPosition = new Vector3( localDeltaPosition.x * rootMotionMultiplier.x, localDeltaPosition.y, localDeltaPosition.z * rootMotionMultiplier.z); Vector3 adjustedDeltaPosition = characterTransform.TransformDirection(adjustedLocalDeltaPosition); if (isDashing || isDodging) { Vector3 deltaPosition = adjustedLocalDeltaPosition; deltaPosition.z *= isDashing ? dashMoveMultiplier : dodgeMoveMultiplier; horizontalMovement = characterTransform.TransformDirection(deltaPosition); } else { horizontalMovement = adjustedDeltaPosition; } verticalMovement = new Vector3(0, animator.deltaPosition.y * rootMotionMultiplier.y, 0); if ( /*!player.statusModule.CanMove ||*/ animationSc.isDisablingMoveXZ) { horizontalMovement = Vector3.zero; } if (animationSc.isDisablingMoveY) { verticalMovement = Vector3.zero; } } private void UpdateRegularMovement() { horizontalMovement = targetDirection.normalized * (moveSpeed * DeltaTime); verticalMovement = Vector3.zero; } /// 落地检测的最短延迟(秒),避免起飞瞬间误判在地面上。 private const float LAUNCH_GROUND_CHECK_DELAY = 0.1f; protected virtual void ApplyGravity() { if (!isApplyingGravity) { currentGravity = Vector3.zero; gravitationalMovement = Vector3.zero; return; } // 击飞脉冲活跃时,Y 轴位移由 ImpulseSubmodule 接管 if (impulseSm.launchImpulse.IsActive) { // 抛物线落地检测:度过起飞延迟且已在下落阶段且触地 → 结束击飞 if (impulseSm.launchImpulse.IsParabolic && impulseSm.launchImpulse.ElapsedTime > LAUNCH_GROUND_CHECK_DELAY && impulseSm.launchImpulse.SampleSignedSpeed() <= 0f && groundDetector.isOnGround) { impulseSm.ClearLaunch(); // 不 return — 落地后立即走正常的 isOnGround 重力分支 } else { currentGravity = Vector3.zero; gravitationalMovement = Vector3.zero; return; } } if (groundDetector.isOnGround) { currentGravity = Vector3.zero; gravitationalMovement = Vector3.zero; movementModifier += Vector3.down * DeltaTime; return; } currentGravity = normalGravity * Vector3.down * DeltaTime; gravitationalMovement += currentGravity * DeltaTime; } protected virtual void UpdateFinalMovement() { horizontalMovement.y = 0; verticalMovement.x = 0; verticalMovement.z = 0; initiativeMovementVelocity = horizontalMovement + (verticalMovement * verticalMoveMultiplier); Vector3 jumpMove = new Vector3(0, jumpVelocity * DeltaTime, 0); Vector3 forceMove = impulseSm.Update(DeltaTime); finalMovementVelocity = initiativeMovementVelocity + gravitationalMovement * verticalMoveMultiplier * gravityMultiplier + forceMove + jumpMove * verticalMoveMultiplier; } protected virtual void InitiativeMove() { if (owner.collisionSc.useCharacterController) { owner.collisionSc.characterController.Move(finalMovementVelocity + movementModifier); } else { Vector3 startPosition = owner.collisionSc.mainRigidbody.position; owner.collisionSc.mainRigidbody.MovePosition(startPosition + finalMovementVelocity + movementModifier); } } } public partial class LandMovementSubcontroller { private void OnDrawGizmos() { if (!Application.isPlaying) return; float groundedOffset = groundDetector?.groundedOffset ?? 0.05f; float groundedRadius = groundDetector?.groundedLength ?? 0.1f; float predictDistance = -character.movementSc.finalMovementVelocity.y; float adjustedRadius = groundedRadius + Mathf.Max(0, predictDistance); Gizmos.color = Color.red; Gizmos.DrawWireSphere(transform.position - new Vector3(0, groundedOffset, 0), adjustedRadius); } } }