dash v2 WIP, prefab corrections, changes for build

This commit is contained in:
2026-01-23 15:14:41 +01:00
parent 916dae1183
commit 0e0262f22d
16 changed files with 1952 additions and 2575 deletions

View File

@@ -14,36 +14,16 @@ namespace Beyond
public bool m_ignoreTriggers = true;
[Header("Beyond Health Logic")]
// Default cap is 1.0 (100% HP)
public float healthRecoveryCap = 1f;
[Header("Beyond's Custom Settings")]
[Tooltip("When 'Use RootMotion' is checked, and this is true, the animation's root motion will control character rotation (for 8-way directional movement). If false, the script will rotate the character to face the input direction.")]
public bool useAnimationBasedRotation = false;
[Header("Beyond's Strafe Combat Settings")]
[Tooltip("The name of the animation state to play when rolling forward while strafing. (This is now disabled)")]
public string strafeRollForwardAnim = "Roll_Forward"; // Kept for reference, but won't be used
[Tooltip("The name of the animation state to play when rolling backward while strafing.")]
public string strafeRollBackwardAnim = "Roll_Backward";
[Tooltip("The name of the animation state to play when rolling left while strafing.")]
public string strafeRollLeftAnim = "Roll_Left";
[Tooltip("The name of the animation state to play when rolling right while strafing.")]
public string strafeRollRightAnim = "Roll_Right";
[Header("Beyond's Dash Settings")]
public string dashBlendTreeState = "Dash_Directional";
// --- UPDATED FIELDS FOR FINER CONTROL ---
[Header("Beyond's Strafe Roll Correction")]
[Tooltip("An additional angle to apply for a LEFT strafe roll.")]
[Range(-90f, 90f)]
public float strafeRollLeftCorrectionAngle = -45f;
[Tooltip("An additional angle to apply for a RIGHT strafe roll.")]
[Range(-90f, 90f)]
public float strafeRollRightCorrectionAngle = 45f;
[Tooltip("An additional angle to apply for a BACKWARD strafe roll. Use 0 for a standard 180-degree roll.")]
[Range(-180f, 180f)]
public float strafeRollBackwardCorrectionAngle = 0f;
// --- END OF UPDATED FIELDS ---
// Internal flag to lock animator parameters during dash
private bool _lockAnimParamsForDash = false;
public bool GodMode
{
@@ -59,10 +39,7 @@ namespace Beyond
{
get
{
// Calculate the actual HP limit based on the cap
float limitHP = maxHealth * healthRecoveryCap;
// Add the check: currentHealth must be LESS than the Limit
return base.canRecoverHealth && (_currentHealth < limitHP);
}
}
@@ -79,124 +56,86 @@ namespace Beyond
protected override void RollBehavior()
{
if (!isStrafing)
{
base.RollBehavior();
return;
}
if (!isRolling)
{
return;
}
Vector3 deltaPosition = new Vector3(animator.deltaPosition.x, 0f, animator.deltaPosition.z);
Vector3 v = (deltaPosition / Time.deltaTime) * (1f - stopMoveWeight);
if (rollUseGravity && animator.GetNormalizedTime(baseLayer) >= rollUseGravityTime)
{
v.y = _rigidbody.linearVelocity.y;
}
_rigidbody.linearVelocity = v;
base.RollBehavior();
}
public override void Roll()
{
if (isStrafing)
{
TriggerStrafeRoll(strafeRollForwardAnim, strafeRollBackwardAnim, strafeRollLeftAnim, strafeRollRightAnim);
}
else
{
OnRoll.Invoke();
isRolling = true;
animator.CrossFadeInFixedTime("Roll", rollTransition, baseLayer);
ReduceStamina(rollStamina, false);
currentStaminaRecoveryDelay = 2f;
}
Dash();
}
public virtual void Dash()
{
if (isStrafing)
{
TriggerStrafeRoll(strafeRollForwardAnim, strafeRollBackwardAnim, strafeRollLeftAnim, strafeRollRightAnim);
}
else
{
OnRoll.Invoke();
isRolling = true;
animator.CrossFadeInFixedTime("Dash", rollTransition, baseLayer);
ReduceStamina(rollStamina, false);
currentStaminaRecoveryDelay = 2f;
}
}
// --- FINAL ROBUST METHOD ---
// This logic now handles all specified cases:
// 1. Sets a base rotation facing the camera to ensure consistency.
// 2. Defaults to a backward roll if input is near-zero (fixing the lingering roll issue).
// 3. Never uses the forward roll; it triggers a backward roll instead.
// 4. Applies a unique correction angle for backward rolls as well as side rolls.
private void TriggerStrafeRoll(string forwardAnim, string backwardAnim, string leftAnim, string rightAnim)
{
OnRoll.Invoke();
isRolling = true;
ReduceStamina(rollStamina, false);
currentStaminaRecoveryDelay = 2f;
string animToPlay;
float correctionAngle = 0f;
// Determine the base "forward" direction from the camera, ignoring vertical tilt.
Vector3 baseForward = Vector3.Scale(Camera.main.transform.forward, new Vector3(1, 0, 1)).normalized;
if (baseForward == Vector3.zero) baseForward = transform.forward; // Fallback
// Set the character's rotation to this base direction. This provides a clean slate.
transform.rotation = Quaternion.LookRotation(baseForward);
// Check if input is negligible (joystick is centered).
// input.sqrMagnitude is more efficient than input.magnitude. 0.1*0.1=0.01.
if (input.sqrMagnitude < 0.01f)
// 1. Handle Stationary (Backwards Dash)
if (input.sqrMagnitude < 0.05f)
{
// If no input, always perform a backward roll.
animToPlay = backwardAnim;
correctionAngle = strafeRollBackwardCorrectionAngle;
ApplyDashParams(0f, -1f);
}
else
{
// If there IS input, determine the dominant direction.
if (Mathf.Abs(verticalSpeed) >= Mathf.Abs(horizontalSpeed))
// 2. Handle Directional Input (Camera Relative -> Character Relative)
// A. Get the Input Direction relative to the Camera
Vector3 inputDir = Vector3.zero;
if (Camera.main != null)
{
// Vertical input is dominant.
// ALWAYS use the backward roll, regardless of forward or backward input.
animToPlay = backwardAnim;
correctionAngle = strafeRollBackwardCorrectionAngle;
// Convert joystick input (X,Y) into World Space based on Camera facing
Vector3 camFwd = Vector3.Scale(Camera.main.transform.forward, new Vector3(1, 0, 1)).normalized;
Vector3 camRight = Vector3.Scale(Camera.main.transform.right, new Vector3(1, 0, 1)).normalized;
inputDir = (camFwd * input.y + camRight * input.x).normalized;
}
else
{
// Horizontal input is dominant.
if (horizontalSpeed > 0)
{
animToPlay = rightAnim;
correctionAngle = strafeRollRightCorrectionAngle;
}
else
{
animToPlay = leftAnim;
correctionAngle = strafeRollLeftCorrectionAngle;
}
// Fallback if no camera found
inputDir = new Vector3(input.x, 0, input.y).normalized;
}
}
// Apply the chosen correction angle if it's not zero.
if (correctionAngle != 0f)
{
transform.Rotate(0, correctionAngle, 0);
}
// Play the selected animation.
animator.CrossFadeInFixedTime(animToPlay, rollTransition, baseLayer);
}
// --- END OF FINAL METHOD ---
// B. Convert that World Direction into the Character's Local Space
// This tells us: "Is the input to the Left, Right, or Forward of ME?"
Vector3 localDir = transform.InverseTransformDirection(inputDir);
// C. Send to Animator
ApplyDashParams(localDir.x, localDir.z);
}
// 3. Play Animation
animator.CrossFadeInFixedTime(dashBlendTreeState, rollTransition, baseLayer);
// 4. Lock parameters briefly so Invector doesn't overwrite them immediately
StartCoroutine(LockDashParamsRoutine());
}
// Helper to set params and lock the update loop
private void ApplyDashParams(float x, float y)
{
_lockAnimParamsForDash = true;
animator.SetFloat(vAnimatorParameters.InputHorizontal, x);
animator.SetFloat(vAnimatorParameters.InputVertical, y);
}
// Release the lock after a short delay (once the blend has firmly started)
private IEnumerator LockDashParamsRoutine()
{
yield return new WaitForSeconds(0.2f); // Adjust this if the blend pops back too soon
_lockAnimParamsForDash = false;
}
// --- CRITICAL FIX: Override Invector's Parameter Update ---
public override void UpdateAnimatorParameters()
{
// If we are locking parameters for the dash, DO NOT let the base class overwrite them.
if (_lockAnimParamsForDash) return;
// Otherwise, run standard Invector logic
base.UpdateAnimatorParameters();
}
// Standard overrides below...
public void OnEvadeStart() { if (!m_GodMode) isImmortal = true; }
public void OnEvadeEnd() { if (!m_GodMode) isImmortal = false; }
public override void ActionsControl() { base.ActionsControl(); m_isDashing = IsAnimatorTag("IsDashing"); }
@@ -286,40 +225,5 @@ namespace Beyond
if (isStrafing || !useAnimationBasedRotation) RotateToDirection(dir);
}
}
public override void UpdateAnimatorParameters()
{
if (disableAnimations) return;
animator.SetBool(vAnimatorParameters.IsStrafing, isStrafing);
animator.SetBool(vAnimatorParameters.IsSprinting, isSprinting);
animator.SetBool(vAnimatorParameters.IsSliding, isSliding && !isRolling);
animator.SetBool(vAnimatorParameters.IsCrouching, isCrouching);
animator.SetBool(vAnimatorParameters.IsGrounded, isGrounded);
animator.SetBool(vAnimatorParameters.IsDead, isDead);
animator.SetFloat(vAnimatorParameters.GroundDistance, groundDistance);
animator.SetFloat(vAnimatorParameters.GroundAngle, GroundAngleFromDirection());
if (!isGrounded) animator.SetFloat(vAnimatorParameters.VerticalVelocity, verticalVelocity);
{
if (isStrafing)
{
animator.SetFloat(vAnimatorParameters.InputHorizontal, horizontalSpeed, strafeSpeed.animationSmooth, Time.fixedDeltaTime);
animator.SetFloat(vAnimatorParameters.InputVertical, verticalSpeed, strafeSpeed.animationSmooth, Time.fixedDeltaTime);
}
else
{
animator.SetFloat(vAnimatorParameters.InputVertical, verticalSpeed, freeSpeed.animationSmooth, Time.fixedDeltaTime);
animator.SetFloat(vAnimatorParameters.InputHorizontal, useAnimationBasedRotation ? horizontalSpeed : 0, freeSpeed.animationSmooth, Time.fixedDeltaTime);
}
animator.SetFloat(vAnimatorParameters.InputMagnitude, Mathf.LerpUnclamped(inputMagnitude, 0f, stopMoveWeight), isStrafing ? strafeSpeed.animationSmooth : freeSpeed.animationSmooth, Time.fixedDeltaTime);
if (useLeanMovementAnim && inputMagnitude >= 0.1f)
{
animator.SetFloat(vAnimatorParameters.RotationMagnitude, rotationMagnitude, leanSmooth, Time.fixedDeltaTime);
}
else if (useTurnOnSpotAnim && inputMagnitude < 0.1f)
{
animator.SetFloat(vAnimatorParameters.RotationMagnitude, (float)System.Math.Round(rotationMagnitude, 2), rotationMagnitude == 0 ? 0.1f : 0.01f, Time.fixedDeltaTime);
}
}
}
}
}