So just a preface: I am a hobbyist game designer/artist trying to make a passion project of my own, but I am pretty new into the coding scene in general. I haven’t been able to find any tutorials online that mirror the jump king precision platformer controls- which is what I am going for. I made a checklist for what I’m looking to accomplish, but I am struggling to figure it out myself. I can get the player moving and jumping but not completely in the way I want.
jumpForce calculated based on how long the JUMP key is held .
Player will automatically jump after hitting the max jumpForce.
Jump direction based only on whether directional key is held while“charging” the jump or . Player will jump straight upward only if no arrow key is held.
Player cannot move while “in the air”. The jump path is fixed as soon as the jump key is released or the jumpForce maxes out.
Player cannot move while “charging up the jump”.
If player collides with terrain while jumping, there is a deflection/bounce-off effect.
Can someone explain how I might be able to hit all these goals in my code? Or point me in the right direction to where/how I might be able to figure it out myself?
I am making a similar game which has two jump heights. If the player releases the space key as soon as he presses it, the character does a normal jump. And if the player holds the space key for more than 0.18 sec, character does a high jump. I implemented it by using WaitForTime(float t) function. when the player presses space key, my character starts the jump with a 20 velocity, and -50 retardation. I initiate a function which continuously checks if space key is released. If it is not released for 0.18 sec, I use the WaitForTime function to set the boolean variable, initiateHighJump to true, which in turn sets the retardation to -15.
Idk if my explanation made sense or not, lol. I am still a newb to Unity and coding, in general, so this is the best of my knowledge.
It doesnt just do 2 different jump heights but is truly based on how long the button is pressed. It shouldnt be too hard to get the Auto jump after max input time pressed after following that tutorial.
i am guessing the player can move on the ground already. So, you would just add another input condition. Right now it seems like If(pressingRight) move right. You want to have another condition, if(pressingRight and then Jumping)…start charging jump and stop movement (your 5th goal).
Basically if the player is not grounded, then they cannot use any left or right inputs. Shouldnt be too difficult to think through once you have a isGrounded bool.
the bounce thing is doable but i would get the major parts of your jump done first and then make another post for the bounce effect. It would be different enough to warrant and once you have the basics of your jump down you may be able to figure it out yourself.
I have 3 different scripts active making this work rn: Camera script, player controller script, and a GatherInput script for my player controller. I’ll post the PlayerController script for now unless ppl want to see the rest. I’m relatively new at programming so any constructive criticism won’t fall on deaf ears.
public class PlayerController : MonoBehaviour
{
public float speed;
public float jumpForce = 0.0f;
private Rigidbody2D rb;
private GatherInput gI;
private Animator anim;
public float rayLength;
public bool grounded;
public bool preJump = false;
public LayerMask groundLayer;
public Transform checkPointLeft;
public Transform checkPointRight;
public PhysicsMaterial2D bounceMat, normalMat;
private int direction = 1;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody2D>();
gI = GetComponent<GatherInput>();
anim = GetComponent<Animator>();
}
private void FixedUpdate()
{
Flip();
SetAnimatorValues();
PlayerJump();
CheckStatus();
PlayerMove();
}
private void PlayerMove()
{
if (jumpForce == 0.0f && grounded)
{
rb.velocity = new Vector2(speed * gI.valueX, rb.velocity.y);
}
}
private void Flip()
{
if(gI.valueX * direction < 0)
{
transform.localScale = new Vector3(-transform.localScale.x, 1, 1);
direction *= -1;
}
}
private void PlayerJump()
{
if(gI.jumpInput && grounded)
{
jumpForce += 0.5f;
rb.velocity = new Vector2(0.0f, rb.velocity.y);
rb.sharedMaterial = bounceMat;
preJump = true;
}
else
{
preJump = false;
}
if (gI.jumpInput && grounded && jumpForce >= 20.0f || gI.jumpInput == false && jumpForce >= 0.1f)
{
float tempX = gI.valueX * speed;
float tempY = jumpForce;
rb.velocity = new Vector2(tempX,tempY);
Invoke("ResetJump", 0.025f);
}
if (rb.velocity.y <= -1)
{
rb.sharedMaterial = normalMat;
}
}
private void ResetJump()
{
jumpForce = 0.0f;
}
private void CheckStatus()
{
RaycastHit2D leftCheckHit = Physics2D.Raycast(checkPointLeft.position, Vector2.down, rayLength, groundLayer);
RaycastHit2D rightCheckHit = Physics2D.Raycast(checkPointRight.position, Vector2.down, rayLength, groundLayer);
if (leftCheckHit || rightCheckHit)
{
grounded = true;
}
else
{
grounded = false;
}
SeeRays(leftCheckHit, rightCheckHit);
}
private void SeeRays(RaycastHit2D leftCheckHit, RaycastHit2D rightCheckHit)
{
Color color1 = leftCheckHit ? Color.green: Color.red;
Color color2 = rightCheckHit ? Color.green: Color.red;
Debug.DrawRay(checkPointLeft.position, Vector2.down * rayLength, color1);
Debug.DrawRay(checkPointRight.position, Vector2.down * rayLength, color2);
}
private void SetAnimatorValues()
{
anim.SetFloat("Speed", Mathf.Abs(rb.velocity.x));
anim.SetFloat("vSpeed", rb.velocity.y);
anim.SetBool("grounded", grounded);
anim.SetBool("preJump", preJump);
}
}
So you know, there’s a much more accurate method of checking if you’re grounded if you define that as being in contact and doesn’t require any spatial queries like raycast etc.
You can see that demonstrated below. It uses Rigidbody2D.IsTouching and passed a filter to filter only the contacts that are “underneath” and on specific layer(s) etc. When the ContactFilter2D is configured in the inspector it comes down to a single line of code too.
No need to visualise rays or any other query, it uses contacts that the physics system has already calculated and uses. You can visualise these contacts by going into Physics 2D Project Settings and turning on “Show Colllider Contacts” in the Gizmos.
The GatherInput script is strictly for the player input using the new input system. Just gathering the X value and whether or not the player is jumping.
Would I have to setup multiple contact filters if I wanted the player to be “grounded” when the rb IsTouching multiple LayerMasks? I want the player to be grounded when standing on top of the ground tilemap, objects, and “moving platforms”
here’s what I went with and it appears to work properly:
public bool grounded => rb.IsTouching(cfGround) || rb.IsTouching(cfObject) || rb.IsTouching(cfPlatform);
public ContactFilter2D cfGround;
public ContactFilter2D cfObject;
public ContactFilter2D cfPlatform;
No, that’s what the ContactFilter2D layerMask is for. Note that this is used not only here but all other 2D physics queries too so it has to allow you to select multiple layers etc.
You should be able to see the above filters in the inspector and select the layers in the drop-down.
Things you cannot do multiple settings of are things such as restructing the angle of the normal you get. It “only” selects you select an arc (range of angles) so if you, for example, wanted contacts that are either below or above then you’d need two only differing by that setting.
For your case though, no, just a single one would do.
Hey Zegley, how are you? I’m a fellow beginner game developer working on a 2d platform project but I’ve had some trouble about the player controller. I’m trying to work on sth like yours. Could you share with me your script? I saw you already shared the PlayerController and Camera script but you also have a ‘GatherInput’ script right? I’d be very hapy if you could share it with me. Thanks already
These 3 scripts are basically all I’m using in this project. Haven’t really worked on it since February/March, but I could probably go into more detail if needed.
Hi, I’m working in my FDP in the superior grade of development and I try to make Jump King but I have some problem with the jump. I tried your code but I don’t understand some problems that show me in Unity. If you can help me,
I would appreciate it a lot.
Hey, I am trying to make a Jump King like game as well. I tried to use your code but i got some problems with the GatherInput one and this is the error : Assets\GatherInput.cs(10,12): error CS0246: The type or namespace name ‘Controls’ could not be found (are you missing a using directive or an assembly reference?) . Do you have any ideea what the cause might be?