0

I've got a problem iam stuck with since 2 days and I can't seem to figure it out.

I have a 2d endless runner in unity with a WorldGenerator and a WorldMover Script. The WorldGenerator uses templates to create the world and the MapMover moves each template to the left so it looks like my character is running all the time.

My CharacterController only handles jumps. So faar my game works perfectly.

But here comes my problem the worldSpeed Chages it gets faster and also can get slower if that happens my characters jump distance (the amount of map scrolling underneath him untill he lands again) changes which makes sense but it makes creating a world impossible since the speed doesn't change at fixed points in the game there are slow tiles and power ups which changes the worldSpeed.

I tryed endless different approaches to have the player always jump the same height, (distance) and projection. But I cannot seem to figure out a working formula to archive this. Also I don't want my character to move on the x axis at all.

In my head it should be as easy as take the original jump let's say when the world moves at speed 5 and just speed the jump up so at speed 5 it takes my character like 1 second to complete the jump so on speed 10 it should take 0.5 seconds. But I cannot get that to work. I tryed changing the gravity and jump force in different formulars with supplying the current world speed but I failed here too most of the time the jump is not the same as before the height, distance or projection always changes. Which is the opposite of what I want.

Hopefully someone can point me in the right direction I be thankful for every Tipp or peace of information I can get.

2 Answers2

0

The problem boils down to having to determine the initial velocity and gravitational acceleration of a projectile (disregarding air friction) with a fixed maximum height and a fixed time to land.

You can look up the fromulas for maximum height and time to land:

formula (maximum height)

formula (time to land)

These can be rearranged for the gravitational acceleration and merged into a formula that can be used to calculate the velocity.

formula

formula

formula

formula

With the calculated velocity you can use a previous formula to determine the gravity.

float v,g,t,s;
v = 4 * s / t;
g = -2 * v / t;

As long as you pick positive values (greater than 0) for t and s you will be able to apply the calculated g and v in your own game system exactly like you intended.

Voidsay
  • 1,462
  • 2
  • 3
  • 15
  • Thanks for your replay it really pointed me in the right I researched some more and found all the kinematic formulas and put together a little calculator I was not able to test it yet but it should work like I intended I will post the code if anyone needs it – heizung124 Mar 15 '23 at 11:39
0

Thanks to Voidsay I put together a little script here is the code I created in case someone needs it. The calculator is a bit overkill for my needs but I thought might aswell complete it.

Edit : I actually found a easyer way to accomplish what i wanted i will leve the code i used before down below but here is the easy way to do it:

    public float jumpHeight = 60; // The desired height of the jump its about / 10
    public float baseGravityScale = 10 f; // Set this scale to the rb
    public float referrenceWorldSpeed = 5 f; // the speed at which all other variables where set
    public FloatVariable worldSpeed; // current world speed
    

    void FixedUpdate() {
        if (Jump) {
            float gravityScale = baseGravityScale * (worldSpeed.value / referrenceWorldSpeed);
            float jumpForce = Mathf.Sqrt(jumpHeight * -2 * Physics2D.gravity.y * rb.gravityScale / gravityScale);
            rb.AddForce(new Vector2(0 f, jumpForce), ForceMode2D.Impulse);
        }
    }

Thats what i used before

using UnityEngine;

public class KinematicMovementCalculator: MonoBehaviour {

        public float initialVelocity;
        public float finalVelocity;
        public float acceleration;
        public float displacement;
        public float time;
    
        public void Calculate() {
    
            if (displacement == 0 f)
    
            {
    
                displacement = (finalVelocity * finalVelocity - initialVelocity * initialVelocity) / (2 f * acceleration);
            } else if (finalVelocity == 0 f)
    
            {
    
                finalVelocity = Mathf.Sqrt(initialVelocity * initialVelocity + 2 f * acceleration * displacement);
            } else if (initialVelocity == 0 f)
    
            {
    
                initialVelocity = Mathf.Sqrt(finalVelocity * finalVelocity - 2 f * acceleration * displacement);
            } else if (acceleration == 0 f)
    
            {
    
                acceleration = (finalVelocity - initialVelocity) / time;
            } else if (time == 0 f)
    
            {
    
                time = (finalVelocity - initialVelocity) / acceleration; >
            } else
    
            {
    
                Debug.LogError("Unable to calculate. Please provide appropriate values."); >
            }
        }
    
        public void Reset() {
    
            initialVelocity = 0 f;
            finalVelocity = 0 f;
            acceleration = 0 f;
            displacement = 0 f;
            time = 0 f;
        }
    }

And here is a jump calculator script

    using UnityEngine;

public class JumpCalculator : MonoBehaviour
{
    public float jumpHeight;
    public float jumpTime;

    private KinematicMovementCalculator _kinematicCalculator;

    private void Awake()
    {
        _kinematicCalculator = new KinematicMovementCalculator();
    }

    public float CalculateInitialVelocity()
    {
        float gravity = Mathf.Abs(Physics.gravity.y);
        float displacement = jumpHeight;
        float timeToApex = Mathf.Sqrt(2f * displacement / gravity);
        float velocityToApex = gravity * timeToApex;
        float velocity = velocityToApex + gravity * jumpTime;

        _kinematicCalculator.initialVelocity = velocity;
        _kinematicCalculator.acceleration = -gravity;
        _kinematicCalculator.time = jumpTime;

        _kinematicCalculator.Calculate();

        return _kinematicCalculator.GetVelocity();
    }
}

I my case I just do jumpHeight 4 JumpTime actuallWorldSpeed / baseWorldSpeed