When I wait a few seconds after my game starts, everything works fine. (When I try to jump, I jump up 29.4, every time I am on the ground, like I am supposed to.)
However the problem lies when I try to jump immediately at the start of my program, my program fails to work properly (just for the first time). I will jump twice as high as I am supposed to, because I collide, I try to jump, it reads through fixed update twice (with the 29.4 code). I have debugged it, and found out it is due to the result of some sort of delay before OnCollisionExit is called, setting the value to 0.
Thinking that the problem might have been with FixedUpdate(), I tried using only update, this really bugged out my program (made it worse). When I tried to jump into the air at the start of the game, I go super high. (Also would happen at random times inside my game as well.) Also my character no longer would rest along the surface of my plane and ends up going 0.02 into it before stopping.
Can someone tell me why there is this delay before exiting the collision sequence (just at the start of the program), and what I can do to correct this issue.
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour
{
public GameObject player;
public float speed;
public float value = 0;
bool isGrounded = false;
void OnCollisionEnter (Collision col)
{
if(col.gameObject.name == "Ground 1")
{
isGrounded = true;
//Debug.Log ("Collision Enter");
}
}
void OnCollisionExit (Collision col)
{
if(col.gameObject.name == "Ground 1")
{
isGrounded = false;
//Debug.Log ("Collision Exit");
}
}
void FixedUpdate ()
{
float moveHorizontal = Input.GetAxis ("Horizontal");
float moveVertical = Input.GetAxis ("Vertical");
//Debug.Log ("Fixed Update");
if(isGrounded == true)
{
if (Input.GetKeyDown (KeyCode.Space))
{value = 9.8f * 3.0f;}
else {value = 0;}
}
else
{
value = 0;
}
Vector3 movement = new Vector3 (moveHorizontal, value , moveVertical);
rigidbody.AddForce(movement * speed * Time.deltaTime);
}
}
Firstly there is this error where my object goes 0.02 into the ground (I’m using a normal sized sphere as my player at the moment for testing purposes), and instead of resting on top y = 0.5, y = 0.48.
What happens with the jump sequence when I change to update is, I hit the ground, I try to jump, at the start of the program, (and every once in a while in the program), it jumps up 2 or more times higher than it is supposed to, before exiting the jump sequence.
Debug Example
Collision Enter
update
value = 29.4
update
value = 29.4
Collision Exit
value = 0
Please correct me if I’m wrong about some of this, I’ve been reading the documentation and I’ve run into this issue before. I’m pretty sure this information should help you out:
It’s very possible that Input.GetKeyDown(KeyCode.Space) is true for multiple FixedUpdate Cycles.
It’s probably better to just to make a broad example of what I’m thinking
Unity Cycle start
Input state checked - Space key pressed is true
Physics Cycle catchup
Physics Cycle catchup
Next Cycle
If you scroll down this document it states that the Physics Cycle can happen multiple times to essentially catch up to the frame update time.
In my opinion, you shouldn’t use Input.GetKeyDown(KeyCode.Space) in the FixedUpdate loop. You should poll that in your Update loop and set a bool in your script when the space button is down, then check for it in the FixedUpdate loop and immediately after you set the Force, set that bool to false. This way you’re reading the correct state of the Space key being pressed within the FixedUpdate loop.
I don’t know about using Input.GetAxis in FixedUpdate either. Basically try to get into the habit of polling input in the Update() call or from an event, whichever is more to your liking.
I apologize for wording this badly. I’m mentally exhausted and I guess I need to pay more attention to the documentation if I can’t fully remember the most important details!
Wow thanks, this helped a lot and fixed the issue I was having. If there are any other changes you feel I should do to improve my code, feel free to reply.
One more thing. Although this is a minor issue (not a bug), when a player hits the space key right before he hits the ground, it sets the bool spaceKeyDown = false. This creates a slight lag in the system, by not allowing the player to jump, right when he hits the ground. Is there any way to make this transition more smooth.
New Working Code
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour
{
public GameObject player;
public float speed;
public float value = 0;
public float moveHorizontal;
public float moveVertical;
bool spaceKeyDown = false;
bool isGrounded = false;
void OnCollisionEnter (Collision col)
{
if(col.gameObject.name == "Ground 1")
{
isGrounded = true;
}
}
void OnCollisionExit (Collision col)
{
if(col.gameObject.name == "Ground 1")
{
isGrounded = false;
}
}
void Update ()
{
moveHorizontal = Input.GetAxis ("Horizontal");
moveVertical = Input.GetAxis ("Vertical");
if (Input.GetKeyDown (KeyCode.Space))
{spaceKeyDown = true;}
else
{spaceKeyDown = false;}
}
void FixedUpdate ()
{
if(spaceKeyDown == true)
{
if(isGrounded == true)
{value = 9.8f * 3.0f;}
else
{value = 0;}
spaceKeyDown = false;
}
else
{value = 0;}
Vector3 movement = new Vector3 (moveHorizontal, value , moveVertical);
rigidbody.AddForce(movement * speed * Time.deltaTime);
value = 0;
}
}
I was playing around with my program, and I noticed another bug.
When I am moving both, forward and left, or backwards and right, at the same time, my character wont jump. (Down and Left, or Up and Right, work fine.)
May not be needed. You can simply allow your FixedUpdate to set the bool to false when your jump actually happens so you don’t have to worry about the Update loop firing multiple times before a FixedUpdate catchup occurs.
Because as it is now, this can happen (We assume for this scenario you’re in the middle of falling to the ground)
Unity Cycle 55
Physics Catchup - (You’ve fallen to the ground, OnColliderEnter should execute and isGrounded = true)
Update Cycle - You press the space key → spaceKeyDown = true
Next Cycle…
Unity Cycle 56
(Not enough time was passed for Physic catchup to occur)
Update Cycle - You didn’t have the space key pressed this frame → spaceKeyDown= false
Next Cycle…
Unity Cycle 57
Physics Catchup - spaceKeyDown is checked and is false even though isGrounded is true, so your jump code is not checked during this Physics Catchup
Update Cycle - You press the space key → spaceKeyDown = true
Next Cycle…
Maybe what you meant to do is switch around your conditions in FixedUpdate a bit. Check to see if you’re grounded first before checking the status of the spaceKeyDown bool. This is more intuitive anyways, because if you can only jump when you’re grounded you’ll want to check if you’re grounded before checking if you can jump! Make Sure you only apply spaceKeyDown is false after assigning the value of your force to be value = 9.8f * 3.0f.
So your condition should look like this
// check to see if you're grounded
if(isGrounded == true)
{
// we're grounded, we can jump if the jump bool is true
if(spaceKeyDown == true)
{
spaceKeyDown = false;
value = 9.8f * 3f;
}
}
Ok, it is working better now. Do you know what is up with my other issue?
When I am moving with the following arrow key combinations while trying to jump…
(Up + Left)- Wont let me jump.
(Up + Right)- Will let me jump.
(Down + Left)-Will let me jump.
(Down + Right)-Wont let me jump.
New Code
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour
{
//Public Variables
public GameObject player;
public float speed;
public float value = 0;
public float moveHorizontal;
public float moveVertical;
bool spaceKeyDown = false;
bool isGrounded = false;
void OnCollisionEnter (Collision col)//Test if player is on the ground
{
if(col.gameObject.name == "Ground 1")
{
isGrounded = true;
}
}
void OnCollisionExit (Collision col)//Test if player is off the ground
{
if(col.gameObject.name == "Ground 1")
{
isGrounded = false;
}
}
void Update ()//For Input Data
{
moveHorizontal = Input.GetAxis ("Horizontal");
moveVertical = Input.GetAxis ("Vertical");
if (Input.GetKeyDown (KeyCode.Space))
{spaceKeyDown = true;}
}
void FixedUpdate ()//For Physics Data
{
JumpData ();
Vector3 movement = new Vector3 (moveHorizontal, value , moveVertical);
rigidbody.AddForce(movement * speed * Time.deltaTime);
value = 0;//Make sure value is 0 after jump sequence.
}
void JumpData()
{
if (isGrounded == true)
{
if (spaceKeyDown == true)
{
spaceKeyDown = false;
value = 9.8f * 3f;
}
else {value = 0;}
}
else {value = 0;}
spaceKeyDown = false;
}
}
This is to see if your Space Key is being detected or not when you have Up + Left, or Down + Right pressed. If it is, you can ignore my next suggestion though its still probably better practice to use Unity’s Binding system whenever possible versus reading input through specific devices –
I would strongly recommend making another Input Axis for the space key and call it “Jump” then replace your Input.GetKeyDown(KeyCode.Space) check with Input.GetButton(“Jump”) and see if you still have the same issues.
I can’t see any immediate reason as to why you can’t jump when you’re moving using certain directions, so to see if the problem exists with how Unity is detecting the Input state between GetAxis and GetKeyDown, try using GetButton over GetKeyDown for the space key.
According to the debug logs, Space Key is not being detected when I have Up + Left, or Down + Right pressed. I tried the other method you showed, and the same scenario occured.
New Code Tested
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour
{
//Public Variables
public GameObject player;
public float speed;
public float value = 0;
public float moveHorizontal;
public float moveVertical;
bool spaceKeyDown = false;
bool isGrounded = false;
void OnCollisionEnter (Collision col)//Test if player is on the ground
{
if(col.gameObject.name == "Ground 1")
{
isGrounded = true;
}
}
void OnCollisionExit (Collision col)//Test if player is off the ground
{
if(col.gameObject.name == "Ground 1")
{
isGrounded = false;
}
}
void Update ()//For Input Data
{
moveHorizontal = Input.GetAxis ("Horizontal");
moveVertical = Input.GetAxis ("Vertical");
//if (Input.GetKeyDown (KeyCode.Space))
//{spaceKeyDown = true;}
if(Input.GetButtonDown("Jump"))
{
spaceKeyDown = true;
Debug.Log("Space Key Pressed. Frame: " + Time.frameCount);
}
}
void FixedUpdate ()//For Physics Data
{
JumpData ();
Vector3 movement = new Vector3 (moveHorizontal, value , moveVertical);
rigidbody.AddForce(movement * speed * Time.deltaTime);
value = 0;//Make sure value is 0 after jump sequence.
}
void JumpData()
{
if (isGrounded == true)
{
if (spaceKeyDown == true)
{
spaceKeyDown = false;
value = 9.8f * 3f;
}
else {value = 0;}
}
else {value = 0;}
spaceKeyDown = false;
}
}
I did some research and it turns out to be a limitation of my keyboard hardware. Keyboard keys form a matrix where each key connects a row to a column (8 rows and 16 columns, for instance). This arrangement allows detection of any two keys at the same time, but three or more keys may not be detected, depending on the rows and columns they connect. If three keys connect R1C1, R1C2 and R2C2, for instance, the circuit can’t identify all of them because they short circuit all four lines when pressed at the same time.
I then found this website that allows you to test what keys are being pressed on your keyboard (or to be more specific, the ones that are being passed to your web browser). I tested those key combinations, and the exact ones I had problems with did not work.
A possible solution stated that i can use the WASD keys instead of the arrow keys, which will work (this issue is why most games do), but I was wondering if there was a possible workaround I could try, to make the arrow keys work for those combinations. .
Consider using the numpad keys or awds as an alternative. Maybe even Mouse clicks (which might be preferred in case you will eventually build your game into a Phone App).
This was pretty enlightening though. My keyboard ran into the same issues during that test.