I get a lot of hang time when jumping up sloping terrain. Is there a fix for this?
Are you referring to the character floating for longer than expected, or falling state not properly switching back to a movement state/animation even though the character has touched down?
The Player remains in the jump position and floats up the undulated slope until the slope levels off once more. Then he drops back into the run/walk/idle.
Hey @Angu5, Jumping on Slopes and Slopes, in general, are a more complicated topic that is not handled in this Course. To my knowledge, the Unity Character Controller component does not have any advanced slope/jump/ground detection algorithm to consider the physics interactions required. You must code additional methods or use a custom Character Controller script to fix the issues. You can read (and implement the code) about this here Physics
It sounds like the state isn’t getting swiched when the stateMachine.CharacteController.isGrounded.
Paste in your PlayerJumpingState() and PlayerFallingState() and we’ll take a look.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerJumpingState : PlayerBaseState
{
private readonly int JumpHash = Animator.StringToHash("Jump");
private Vector3 momentum;
private const float CrossFadeDuration = 0.1f;
public PlayerJumpingState(PlayerStateMachine stateMachine) : base(stateMachine) { }
public override void Enter()
{
stateMachine.ForceReceiver.Jump(stateMachine.JumpForce);
momentum = stateMachine.Controller.velocity;
momentum.y = 0f;
stateMachine.Animator.CrossFadeInFixedTime(JumpHash, CrossFadeDuration);
stateMachine.LedgeDetector.OnLedgeDetect += HandleLedgeDetect;
}
public override void Tick(float deltaTime)
{
Move(momentum, deltaTime);
if (stateMachine.Controller.velocity.y <= 0)
{
stateMachine.SwitchState(new PlayerFallingState(stateMachine));
return;
}
FaceTarget();
}
public override void Exit()
{
stateMachine.LedgeDetector.OnLedgeDetect -= HandleLedgeDetect;
}
private void HandleLedgeDetect(Vector3 ledgeForward, Vector3 closestPoint)
{
stateMachine.SwitchState(new PlayerHangingState(stateMachine, ledgeForward, closestPoint));
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerFallingState : PlayerBaseState
{
private readonly int FallHash = Animator.StringToHash("Fall");
private Vector3 momentum;
private const float CrossFadeDuration = 0.1f;
public PlayerFallingState(PlayerStateMachine stateMachine) : base(stateMachine) { }
public override void Enter()
{
momentum = stateMachine.Controller.velocity;
momentum.y = 0f;
stateMachine.Animator.CrossFadeInFixedTime(FallHash, CrossFadeDuration);
stateMachine.LedgeDetector.OnLedgeDetect += HandleLedgeDetect;
}
public override void Tick(float deltaTime)
{
Move(momentum, deltaTime);
if (stateMachine.Controller.isGrounded)
{
ReturnToLocomotion();
}
FaceTarget();
}
public override void Exit()
{
stateMachine.LedgeDetector.OnLedgeDetect -= HandleLedgeDetect;
}
private void HandleLedgeDetect(Vector3 ledgeForward, Vector3 closestPoint)
{
stateMachine.SwitchState(new PlayerHangingState(stateMachine, ledgeForward, closestPoint));
}
}
Looking at your gif, you can try the following :
- increase the jump height (force) and see if you still have the issue on slopes
My guess on what’s happening (as mentioned in my previous post, this is a more complicated issue)
- you jump and hit a slope > the momentum pushes you forward (since you are still in the jump state and not falling state), making your vertical velocity positive and invalidating this condition
if (stateMachine.Controller.velocity.y <= 0)
{
stateMachine.SwitchState(new PlayerFallingState(stateMachine));
return;
}
Add a debug in your tick method. Then check the vertical velocity on a slope where this issue is happening.
public override void Tick(float deltaTime)
{
Move(momentum, deltaTime);
Debug.Log("Vertical Velocity is "+ stateMachine.Controller.velocity.y );
if (stateMachine.Controller.velocity.y <= 0)
{
stateMachine.SwitchState(new PlayerFallingState(stateMachine));
return;
}
FaceTarget();
}
Here is a quick test I made to re-create the issue you have, and changing the force fixes it for now. you can see my velocity in the bottom left corner
It looks in the gif as if the ForceReceiver.Jump is getting a second hit, you’ll note that the character reaches the ground with a - y in place, and then suddenly reverses and has a positive y, making another arc… At least thats’ what I’m seeing…
that being said, I don’t see any logic in the two states that would cause this.
Add some Debugs to JumpingState and FallingStat Enter and Exit, as well as ForceReceiver.Jump. On One Jump, you should see
JumpingState Enter
ForceReciever Jump
JumpingState Exit
FallingState Enter
FallingState Exit.
In tht order
I upped the JumpForce to 7 still getting the same issue.
Hmm,
- Did you also try to set a high number like 20 for the jump force?
- is your jumping working correctly on flat ground? By correct, I mean the capsule collider should move, not just the mesh.
- Are you using root motion by any chance? Can you please double-check?
- Did you try with a different jump animation?
- Is that Debug Log you posted for one jump or multiple? If it’s just one jump, maybe Brian is onto something with the jump event being triggered again, but I have no idea how that is possible,
It would also be helpful if you shared a youtube link to your videos (rather than a Gif). You can upload them as Unlisted, and only the people with the link will see them.
It looks like it’s not falling out of the jumping state till you get to the top in this one (based on the count of debug.logs in the gif, I can’t read them in the gifs).
Let’s add something to force a trip to fallingstate even if the ForceReceiver still thinks there is more momentum
if (stateMachine.Controller.velocity.y <= 0 || stateMachine.Controller.isGrounded)
{
stateMachine.SwitchState(new PlayerFallingState(stateMachine));
return;
}
Thanks Brian, this seams to work. There is a bit of a tick in the motion but it is probably more related to the animation. I will try to link a video soon.
This demonstrates that the cause is likely the force receiver still having upward lift while the character should have touched down. The steeper the slope, the more likely that is to happen. In real life, if you attempted to leap up a slope of that size, but didn’t have enough vertical for the steepness of the slope, you’d risk an ugly tripping when your feet hit the slope prematurely… For those of you implementing D&D style stats, that’s a good spot for an agility check.