Forum rules - please read before posting.

Change Player's Forward Movement Vector?

I want my player to be able to walk up a steep slope. Just using a No Friction physics material is not good enough, he's still getting stuck. 

To make the player "stick" to the surface and move smoothly, I want his "forward" vector to match the ground's normal direction.

So a raycast is shot down, determines the ground's normal direction, and sets the player's forward direction based on that. 

The difference is that a player moving with transform.forward who runs into a slope, is colliding with the slope and physics pushing him up. On the contrary, I want to move the player in the direction of the ground below him

I see that SetMoveDirectionAsForward() from line 1551 of Char.cs is being called, which is setting the moveDirection to tranform.forward.

Instead, I want to set this to a cross of the ground's normal direction:
if (Physics.Raycast(transform.position + new Vector3(0f, 0.1f, 0f), Vector3.down, out hit, 1f, raycastCollisionMask)) {
    forward = Vector3.Cross(transform.right, hit.normal);
}
else {
    forward = transform.forward;
}

I can Debug.DrawRay and see the Vector is fine, and matches the slope of the ground. However, when my player walks up a slope, he "Flies" up into the air. I have a hard time understanding how gravity is applied. 

I see that in MoveRigidbody() line 1057 Char.cs, a Force is calculated that uses _rigidbody.velocity.y. This is why my character flies into the sky, because the slope gives him a positive velocity and then the CalcForce() function keep sending him up.

Any suggestion how I can implement this "Raycast for ground, and set player's forward vector based on ground's normal" system without sending the player to the sky?

Comments

  • Does the same things happen with Tin Pot?  Please share some images (or even a scene file) so that I can see the behaviour for myself.

    Unless you have a specific need for a Rigidbody, you do have the option of using a Character Controller component instead of the Rigidbody + Capsule Collider.  That features a "Slope limit" field that gives better control over slopes.
  • Yes, Tin Pot got stuck trying to go up a slope that was too steep. I found a solution:

    In Char.cs I've made a new function to check if the player is standing on Flat Ground, Facing Uphill, or Facing Downhill (float groundState: -1 = downhill, 0 = flat ground, 1 = uphill):

    private void SetGroundStatus() {
                Vector3 forward = Vector3.zero;
                RaycastHit hit;
                if (Physics.Raycast(transform.position + new Vector3(0f, 0.1f, 0f), Vector3.down, out hit, 0.5f)) { //, raycastCollisionMask
                    forward = Vector3.Cross(transform.right, hit.normal);
                }
                else {
                    forward = transform.forward;
                }
                
                float angle = Vector3.Angle(transform.forward, forward);
                Vector3 cross = Vector3.Cross(Vector3.forward, forward);
                if (cross.x > 0) angle = -angle;
                // Uphill
                if (angle > 1f) {
                    groundState = 1f;                
                }
                // Downhill
                else if (angle < -1f) {
                    groundState = -1f;
                }
                // Flat ground
                else {
                    groundState = 0f;
                    forward = transform.forward;
                }
            }

    If the player is facing uphill, then I will give him a small boost to the Y value of his forward vector. This was done at Char.cs function SetMoveDirectionAsForward():

    public void SetMoveDirectionAsForward () {
        SetGroundStatus();
        isReversing = false;
        moveDirection = transform.forward;
        if (groundState == 1f) { moveDirection += Vector3.up * 0.1f; }

    So if the character is moving uphill, his forward vector is NOT transform.forward, but a vector that is facing slightly upwards too. Now the physics force pushes him UP the hill.

  • I have to admit I don't see any noticeable slowdown with Tin Pot walking up even very steep slopes, but I think this is one of those areas where customisation is necessary to get exact behaviour needed for a project.

    The suggestion you've posted might work for your character and scale, but wouldn't be transferrable without introducing a lot more variables that the user has to tweak.  The amount of lift may need changing according to the steepness of the slope, or be negative when travelling downwards, etc.

    I feel the fine tuning necessary makes this best suited to custom script delegation, IMO, similar to the way inputs can be overridden.

    I'll PM you a test package with updated Char/Enum scripts along with a new "CustomController" example script that hooks into an experimental SetMovementDirectionDelegate, which is called automatically whenever the moveDirection is updated.  This way, you can tweak the vector as necessary, and return it back, any way you like without having to modify AC's script or rely on a totally custom motion controller.
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.