- Home /
Marble refuses to jump sometimes
I have a marble rolling game controlled by UI buttons for mobile. I'm using the SendMessage system to have the buttons talk to the Player Movement script. The jumping works most of the time, but sometimes randomly it would refuse to jump, thus really messing up the experience. Also, sometimes when it refuses to jump, it would apply 2x the force when I jump again making the marble jump 2x higher. I tried a cooldown script to prevent this 2x force. I think it reduced the amount of 2x jump, but it still happens.
I've been trying to fix this for days to no avail. Here's my code:
using UnityEngine;
using System.Collections;
public class PlayerMovement : MonoBehaviour {
public float spinTorque;
public float airSpeed;
public float MaxAngularVelocity;
private Vector3 Jump;
public float JumpStrength = 1000;
public GameObject Camera;
public AudioSource CollisionSound;
public float RollDrag = 1;
public AudioSource JumpSound;
public AudioSource RollSound;
public AudioSource BounceSound;
public CNAbstractController MovementJoystick;
private bool inAir = true;
private bool isJumping = false;
private Vector3 NormalDirection;
// Use this for initialization
void Start () {
inAir = true;
RollSound.Play ();
GetComponent<Rigidbody>().maxAngularVelocity = MaxAngularVelocity;
}
void FixedUpdate () {
print (inAir);
//Ball air and spin movement.
//Airspeed
float hf = MovementJoystick.GetAxis ("Horizontal") * airSpeed * Time.deltaTime; //Touch Joystick Input
float vf = MovementJoystick.GetAxis ("Vertical") * airSpeed * Time.deltaTime;
float jhf = Input.GetAxis ("Horizontal") * airSpeed * Time.deltaTime; //Keyboard/Joystick Input
float jvf = Input.GetAxis ("Vertical") * airSpeed * Time.deltaTime;
float h = MovementJoystick.GetAxis ("Horizontal") * spinTorque * Time.deltaTime; //Touch Joystick Input
float v = MovementJoystick.GetAxis ("Vertical") * spinTorque * Time.deltaTime;
float jh = Input.GetAxis ("Horizontal") * spinTorque * Time.deltaTime; //Keyboard/Joystick Input
float jv = Input.GetAxis ("Vertical") * spinTorque * Time.deltaTime;
if (inAir == true) {
GetComponent<Rigidbody> ().AddForce (Camera.transform.right * hf);
GetComponent<Rigidbody> ().AddForce (Camera.transform.forward * vf);
GetComponent<Rigidbody> ().AddForce (Camera.transform.right * jhf);
GetComponent<Rigidbody> ().AddForce (Camera.transform.forward * jvf);
}
GetComponent<Rigidbody> ().AddTorque (Camera.transform.forward * -h);
GetComponent<Rigidbody> ().AddTorque (Camera.transform.right * v);
GetComponent<Rigidbody> ().AddTorque (Camera.transform.forward * -jh);
GetComponent<Rigidbody> ().AddTorque (Camera.transform.right * jv);
}
void Update () {
// Sound pitch control
if (inAir == false) {
RollSound.volume = GetComponent<Rigidbody> ().velocity.magnitude / 15;
RollSound.pitch = GetComponent<Rigidbody> ().velocity.magnitude / 25 + 0.3f;
RollSound.pitch = Mathf.Clamp (RollSound.pitch, 0.1f, 1f);
} else {
RollSound.volume = 0;
}
}
void OnCollisionStay (Collision collision) {
//Jump effects.
NormalDirection = collision.contacts [0].normal;
if (isJumping == true) {
StartCoroutine(JumpCooldown());
}
}
void OnCollisionEnter (Collision collision){
CollisionSound.volume = collision.relativeVelocity.magnitude/100;
CollisionSound.Play ();
inAir = false;
GetComponent<Rigidbody> ().drag = RollDrag;
}
void OnCollisionExit (){
inAir = true;
GetComponent<Rigidbody> ().drag = 0;
}
void JumpActive (){
StopCoroutine (Jumping ());
StartCoroutine (Jumping ());
}
IEnumerator Jumping (){
isJumping = true;
yield return new WaitForSeconds (0.01f);
isJumping = false;
}
IEnumerator JumpCooldown(){
GetComponent<Rigidbody>().AddForce(NormalDirection * JumpStrength);
JumpSound.Play ();
yield return new WaitForSeconds (0.05f);
}
}
Answer by austint30 · Aug 24, 2015 at 11:51 AM
I managed to figure it out. You just have to make sure that your jumping is in Update. You can use a boolean to find if it is jumping or not. The boolean can be isJumping that is switched to true when the jump button is pressed and then switched back to false after the marble has jumped.
Answer by FortisVenaliter · Aug 21, 2015 at 04:24 PM
Honestly, I would get rid of the built-in collision detection entirely. If it's a ball, it would be much easier to do a downward raycast, and detect whether you're jumping by the distance from origin to ground. If it's less than or equal to radius, then it's on the ground, otherwise it's in the air.
That would be harder, since it doesn't account for slopes, and requires extra code. The built-in collision detection is perfectly fine. This isn't the problem anyway.
Answer by Eric5h5 · Aug 21, 2015 at 04:49 PM
You haven't included the jump input code, so it's not really possible to answer, but it sounds like the sort of thing that happens when you're doing input in FixedUpdate. Since FixedUpdate doesn't run every frame, it can miss input that only occurs for one frame.
The jump function is called by an external button using the Send$$anonymous$$essage feature.
That doesn't really answer anything about what I said. Are you using FixedUpdate to detect jump input or not?
It's not on the Update nor FixedUpdate. It's on the OnCollisionStay.
void OnCollisionStay (Collision collision) {
//Jump effects.
NormalDirection = collision.contacts [0].normal;
if (isJumping == true) {
StartCoroutine(JumpCooldown());
}
}
It also on an IENumerator that is called by the OnCollisionStay.
Here is the IENumerator
IEnumerator JumpCooldown(){
GetComponent<Rigidbody>().AddForce(NormalDirection * JumpStrength);
JumpSound.Play ();
yield return new WaitForSeconds (0.05f);
}
Your answer
Follow this Question
Related Questions
OnCollision Jump Occurring Twice 1 Answer
jump at opposite angle of surface 2 Answers
onCollisioStay only for specific objects 1 Answer
One object move and collide then jump up to other object... 1 Answer
Overriding another OnCollisionStay 0 Answers