Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to jump to a point using CharacterController?

Tags:

c#

unity3d

I have a script to jump, but it jumps depending on the value of the JumpFactor constant. I would like the jump to happen using the JumpToPositionX (float target) method. I think I need to somehow calculate the JumpFactor depending on the value of the target in the JumpToPositionX method. I found an article on Wikipedia, but I don't even know where to start. I have not found examples of how to do this with the CharacterController.

public class ExampleClass : MonoBehaviour
{
    const float Speed = 6f;
    const float JumpFactor = 14f;
    const float Gravity = 20f;
    
    private Vector3 moveDirection = Vector3.zero;

    CharacterController controller;

    void Start()
    {
        controller = GetComponent<CharacterController>();
    }

    void Update()
    {
        if (controller.isGrounded)
        {
            moveDirection = new Vector3(1f, 0f, 0f); // Move X Direction
            moveDirection *= Speed;
            if (Input.GetButton("Jump"))
                moveDirection.y = JumpFactor;

        }
        moveDirection.y -= Gravity * Time.deltaTime;
        controller.Move(moveDirection * Time.deltaTime);
    }

    // Method for jump, calling from other script.
    void JumpToPositionX(float target)
    {
    }
}
like image 461
Aimon Z. Avatar asked Mar 02 '23 00:03

Aimon Z.


1 Answers

Theory

I assume you want to use the ballistic physic.

Let's see what formula we can use

speedFormula

positionFormula

Where :

  • V : Velocity
  • a : Acceleration
  • P : Position
  • t : time since start
  • 0 : Initial

is known it's (0f,-9.81f) or (0f, Gravity) in your case.

is known too, it's your initial position before the jump.

is the end target position.

Resolution

You have to find the end time and the initial Velocity . So here's the position equation:

We can simplify the process by looking only for the x axis because there's no acceleration.

is simplified to :

Let's isolate the from the x position formula :

Now you have the total time of the jump . You just need to find the initial y velocity by using the y position formula :

Isolate the Vyo :

So now you have all informations for computing the jump : Initial and end position, Total time, Initial velocity and acceleration.

Implementation

Here's an example of the MonoBehaviour you can create :

public class JumpBehaviour : MonoBehaviour
{

    public CharacterController CharacterController;

    public Transform TargetPosition;

    private bool jumpStarted = false;
    private float totalTime = 0f;
    private float t = 0f;
    private Vector2 V0;

    private Vector2 initialPosition;

    private bool jumpKeyDown;

    private const float xSpeed = 6f;
    private const float gravity = -9.81f;

    void Update()
    {
        jumpKeyDown = Input.GetKeyDown(KeyCode.Space);
    }

    void FixedUpdate()
    {
        if (jumpStarted)
        {
            UpdateJumpPosition(Time.fixedDeltaTime);
        }
        else if (jumpKeyDown )
        {
            StartJump();
        }
    }

    private void UpdateJumpPosition(float deltaTime)
    {
        t += deltaTime;

        if(t > totalTime)
        {
            //End of jump
            transform.position = TargetPosition.position;
            jumpStarted = false;
            return;
        }

        Vector2 newPosition = new Vector2(0f, gravity) * t * t + V0 * t + initialPosition;

        CharacterController.Move(newPosition);
    }

    private void StartJump()
    {
        jumpStarted = true;

        initialPosition = transform.position;

        // Absolute because xSpeed could be positive or negative. We dont want negative time
        float delta = TargetPosition.position.x - transform.position.x;
        totalTime = Mathf.Abs(delta / xSpeed);
        t = 0f;

        float yInitialSpeed = (TargetPosition.position.y - transform.position.y - gravity * totalTime * totalTime) / totalTime;

        // Using Sign to set the direction of horizontal movement
        V0 = new Vector2(xSpeed * Mathf.Sign(delta), yInitialSpeed);
    }
}

And this is the result unity result

Conclusion

This is just an quick example to figure out how to compute the initial value of the jump and movement in 2D. As derHugo said on comment you should not use transform.position direct attribution with Physic.

For 3D it's the same idea but you should compute the speed x,z from target direction and speed magnitude.

Vector3 delta = TargetPosition - transform.position;
delta.y = 0f;
float direction = delta.normalized;
Vector3 initialSpeed = direction * movementSpeed;
like image 118
D.B Avatar answered Mar 09 '23 06:03

D.B