Here’s a doozy. Can’t figure it out for the life of me. Once I die, grounded is permanently stuck on false. If I set it true after I die using the Inspector, crouching will set it to false as well as dying. I can’t jump at all!
Do not put code for your character in your platforms you may have hundreds of these and its code that isn’t needed, it should be controlled through your character and will lead to bugs.
You seem to be having issues getting your character controller working so I suggest going through the tutorial Unity has on 2D Character Controllers. I followed this tutorial when I started using Unity and it helped a lot.
EDIT: Okay, new problem. I can’t jump at all after removing PlatformTop, and grounded is constantly set to false. There is NOTHING I can see wrong with my script.
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour
{
public float maxSpeed = 10f;
bool facingRight = true;
Animator anim;
public float jumpForce = 50f;
public float normalfall = 2f;
public float fastfall = 5f;
public bool grounded;
public bool dead;
public GameObject platform;
void Start ()
{
anim = GetComponent<Animator>();
this.rigidbody2D.gravityScale = normalfall;
}
void Update ()
{
if (grounded)
{
if (Input.GetButton ("Down"))
anim.SetBool ("Crouch", true);
else
anim.SetBool ("Crouch", false);
}
else
{
if (Input.GetButton ("Down"))
this.rigidbody2D.gravityScale = fastfall;
else
this.rigidbody2D.gravityScale = normalfall;
}
}
void FixedUpdate ()
{
anim.SetFloat ("vSpeed", rigidbody2D.velocity.y);
float move = Input.GetAxis ("Horizontal");
anim.SetFloat ("Speed", Mathf.Abs (move));
if (move > 0 && !facingRight)
Flip ();
else if (move < 0 && facingRight)
Flip ();
rigidbody2D.velocity = new Vector2 (move * maxSpeed, rigidbody2D.velocity.y);
}
void OnCollisionStay ()
{
grounded = true;
anim.SetBool ("grounded", true);
if (Input.GetButtonDown ("Jump"))
{
rigidbody2D.AddForce(new Vector2(0, jumpForce));
grounded = false;
anim.SetBool ("grounded", false);
}
}
void Flip()
{
facingRight = !facingRight;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
}
OnCollisionStay() is the 3D function and will be fired as long as player is touching anything that is a 3D collider not set to be a trigger.
Use OnCollisionEnter2D(Collider2D other) and check if the collider is ground and if it is set grounded to true. This will only trigger once.
Make move a class variable, and add another boolean called jumping.
then update your Update() and FixedUpdate()
void Update()
{
if (grounded)
{
//put all code that you can do on the ground here.
if (Input.GetButton("Down"))
anim.SetBool("Crouch", true);
else
anim.SetBool("Crouch", false);
if (Input.GetButton("Jump"))
jumping = true;
}
else
{
//put anything that you can do while in the air here
if (Input.GetButton("Down"))
this.rigidbody2D.gravityScale = fastfall
else
this.rigidbody2D.gravityScale = normalfall;
}
move = Input.GetAxis("Horizontal");
anim.SetFloat("Speed", Mathf.Abs(move));
}
void FixedUpdate()
{
rigidbody2D.velocity = new Vector2(move * maxSpeed, rigidbody2D.velocity.y);
anim.SetFloat("vSpeed", rigidbody2D.velocity.y);
if (move > 0 && !facingRight)
Flip();
else if (move < 0 && facingRight)
Flip();
if (jumping)
{
rigidbody2D.AddForce(new Vector2(0, jumpForce));
jumping = false;
}
}
I am using the CompareTag function because using other.tag == “ground” will generate garbage, more specifically other.tag will return a copy of the string and not a reference(strings are hell on the garbage collector if you don’t know what to do with them.) CompareTag does the == internally so it uses the actual string to do the compare.
This is only one way to do what you are trying to accomplish. Follow the tutorial it will show you how to make a character controller that is more robust.
Yeah, it works fine. Let me check my script for a moment.
Okay, so here’s all the relevant information compiled into a convenient JumpScript complete with fast-fall:
using UnityEngine;
using System.Collections;
public class JumpScript : MonoBehaviour
{
public float jumpForce = 50f;
public float normalfall = 2f;
public float fastfall = 5f;
public float maxSpeed = 10f;
public float move;
public bool grounded;
Animator anim;
void Start ()
{
anim = GetComponent<Animator>();
this.rigidbody2D.gravityScale = normalfall;
}
void Update ()
{
if (GameObject.Find("Platform Top").GetComponent<PlatformTop>().pressure1)
{
grounded = true;
}
else
{
grounded = false;
}
if (grounded)
{
anim.SetBool("grounded", true);
if (Input.GetButton("Down"))
anim.SetBool("Crouch", true);
else
anim.SetBool("Crouch", false);
if (Input.GetButtonDown("Jump"))
rigidbody2D.AddForce(new Vector2(0, jumpForce));
}
else
{
anim.SetBool("grounded", false);
if (Input.GetButton("Down"))
this.rigidbody2D.gravityScale = fastfall;
else
this.rigidbody2D.gravityScale = normalfall;
}
}
void FixedUpdate()
{
rigidbody2D.velocity = new Vector2(move * maxSpeed, rigidbody2D.velocity.y);
anim.SetFloat("vSpeed", rigidbody2D.velocity.y);
}
}
And its’ buddy, PlatformTop.
using UnityEngine;
using System.Collections;
public class PlatformTop : MonoBehaviour
{
public bool pressure1;
void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.CompareTag("Player1"))
{
pressure1 = true;
}
}
void OnCollisionExit2D(Collision2D other)
{
if (other.gameObject.CompareTag("Player1"))
{
pressure1 = false;
}
}
}
This does not include horizontal movement and its’ only purrpose is to allow the user to jump. My full script also allows horizontal movement but I took out that part to show you what I did.