Falling animation when on slopes - c#

I'm pretty new to all of this so sorry for rookie mistakes.
I've built a State Machine that I'm pretty happy with, with just one problem, whenever the player jumps on a slope and keeps running (either up or down) the animation won't switch to running and stays at falling.
private void FixedUpdate()
{
GroundCheck();
if (state != State.hurt)
{
Movement();
DoubleJump();
StateMachine();
}
HurtCheck();
anim.SetInteger("state", (int)state);
}
private void Movement()
{
float hDirection = Input.GetAxis("Horizontal");
//holding down "D" makes the value positive and vice versa
if (hDirection < 0)
{
rb.velocity = new Vector2(-speed, rb.velocity.y);
transform.localScale = new Vector2(-1, 1);
}
else if (hDirection > 0)
{
rb.velocity = new Vector2(speed, rb.velocity.y);
transform.localScale = new Vector2(1, 1);
}
else
{
}
if (Input.GetButtonDown("Jump") && isGrounded == true)
{
Jump();
}
}
private void StateMachine()
{
if(rb.velocity.y > 2f && isGrounded == false)
{
state = State.jumping;
}
if(rb.velocity.y < 2f && isGrounded == false)
{
state = State.falling;
}
if(rb.velocity.y == 0 && Mathf.Abs(rb.velocity.x) > 2f)
{
state = State.running;
}
if(rb.velocity.magnitude == 0)
{
state = State.idle;
}
}

It looks like you intend rb.velocity.y to be greater than 0 when on a slope. But in order to enter the running state you have a condition that rb.velocity.y == 0. If you want to run on a slope, then maybe you should change that condition like this.
if((rb.velocity.y < 2f) && (Mathf.Abs(rb.velocity.x) > 2f))
{
state = State.running;
}

Related

Platformer Double-Jump and Dash Not Working

Working on a platformer where as the player moves over an energy orb, they can choose to fuel either a double jump or a dash. No errors according to unity, but when I press the corresponding keys for my double jump and dash, neither work. Simply nothing happens. Oh and btw my character randomly freezes and I have to tap the movement key again to get him to continue moving this is also a new issue so may be related. I am very new to all this.
public class playerMovement : MonoBehaviour
{
[SerializeField] private float speed;
[SerializeField] int dashEnergy = 1;
[SerializeField] int doubleJumpEnergy = 1;
private Rigidbody2D body;
private Animator anim;
private int jumpCount;
private void Awake()
{
body = GetComponent<Rigidbody2D>();
}
private void Update()
{
//Left-Right Movement
float horizontalInput = Input.GetAxis("Horizontal");
if(Input.GetKey(KeyCode.Space) && jumpCount == 0)
{
jump();
jumpCount += 1;
}
body.velocity = new Vector2(horizontalInput*speed, body.velocity.y);
//Character Turns Towards Movement Direction
if (horizontalInput > 0.01f)
transform.localScale = new Vector3(-5, 5, 5);
if (horizontalInput < -0.01f)
transform.localScale = new Vector3(5,5,5);
//Dash & doubleJump
void doubleJump()
{
if(Input.GetKey(KeyCode.Space)&&jumpCount==1 && doubleJumpEnergy==1)
{
jump();
doubleJumpEnergy -= 1;
}
}
void Dash()
{
if(Input.GetKey(KeyCode.LeftShift) && dashEnergy == 1)
{
body.velocity = new Vector2(horizontalInput*speed*60, body.velocity.y);
dashEnergy -=1;
}
}
}
public void jump()
{
body.velocity = new Vector2(body.velocity.x, speed);
}
private void OnCollisionEnter2D(Collision2D collision)
{
if(collision.gameObject.tag == "EnergyBubble" && Input.GetKey(KeyCode.V))
{
dashEnergy += 1;
}
if(collision.gameObject.tag == "EnergyBubble" && Input.GetKey(KeyCode.C))
{
doubleJumpEnergy += 1;
}
if (collision.gameObject.tag == "Ground")
{
jumpCount=0;
}
}
}
Firstly, all physics operations should be used from fixedUpdate method, for example:
void FixedUpdate()
{
if (Input.GetButtonDown("Space"))
rb.velocity = new Vector2(0, 10);
}
It's needs for smoothly physics movement.
Or call your own method from it:
void FixedUpdate()
{
if (Input.GetButtonDown("Space"))
jump();
}
Then you have a bug in condition check statements, you have to use:
//Dash & doubleJump
if (Input.GetKey(KeyCode.Space) && jumpCount == 1 && doubleJumpEnergy >= 1)
{
body.velocity = new Vector2(0, 2);
doubleJumpEnergy -= 1;
}
if (Input.GetKey(KeyCode.LeftShift) && dashEnergy >= 1)
{
body.velocity = new Vector2(horizontalInput * speed * 60, body.velocity.y);
dashEnergy -= 1;
}
Problem with a condition check statements, you need to have ">=" operator: dashEnergy >= 1 and doubleJumpEnergy >= 1 instead ==

how to make your jump forgiving in unity 2d?

you know in good platform games the jump is forgiving like if you jumped and your collider isn't touching the ground after you touch the ground the player jump automatically I trayed to do it with a timer but some times the jump delays.
void Jump(bool isPressed)
{
if (isPressed && Ccollider2D.IsTouchingLayers(LayerMask.GetMask("Ground")))
{
rb.velocity = new Vector2(rb.velocity.x, 0f);
rb.velocity += new Vector2(0f, jumpForce);
}
else if (isPressed && Bcollider2D.IsTouchingLayers(LayerMask.GetMask("Ground")) && Ccollider2D.IsTouchingLayers(LayerMask.GetMask("Ground")) == false)
{
StartCoroutine(jumpWait());
}
}
IEnumerator jumpWait()
{
yield return new WaitForSeconds(0.08f);
if (Ccollider2D.IsTouchingLayers(LayerMask.GetMask("Ground")))
{
rb.velocity = new Vector2(rb.velocity.x, 0f);
rb.velocity += new Vector2(0f, jumpForce);
}
}
what is the actual method to do it
There’s no way for me to be sure of the function of Bcollider2D and Ccollider2D in your code, but for the timer you’d likely be better off using something like this:
float tryJumpTime = 0;
void Jump(bool isPressed)
{
if ( (isPressed || tryJumpTime > Time.time) && Ccollider2D.IsTouchingLayers(LayerMask.GetMask("Ground")))
{
rb.velocity = new Vector2(rb.velocity.x, 0f);
rb.velocity += new Vector2(0f, jumpForce);
}
else if (isPressed && Bcollider2D.IsTouchingLayers(LayerMask.GetMask("Ground")) && Ccollider2D.IsTouchingLayers(LayerMask.GetMask("Ground")) == false)
{
tryJumpTime = Time.time + 0.08f;
}
}

jump animation ending too quickly in first jump

void FixedUpdate()
{
moveInput = Input.GetAxis("Horizontal");
rb.velocity = new Vector2(moveInput * speed, rb.velocity.y);
anim.SetBool("isWalking", true);
if (facingRight == false && moveInput>0)
{
flip();
}
else if (facingRight == true && moveInput < 0)
{
flip();
}
else if (moveInput == 0)
{
anim.SetBool("isWalking", false);
}
isGrounded = Physics2D.OverlapCircle(groundCheck.position, checkRadius, whatIsGround);
}
void Update()
{
if (isGrounded == true)
{
Debug.Log("is grounded");
extraJumps = extraJumpValue;
anim.SetBool("isJumping", false);
}
if (Input.GetKeyDown(KeyCode.Space) && extraJumps + 1.0f > 0)
{
jump();
extraJumps--;
}
}
void flip()
{
facingRight = !facingRight;
Vector3 Scaler = transform.localScale;
Scaler.x *= -1;
transform.localScale = Scaler;
}
void jump()
{
rb.velocity = Vector2.up * jumpForce;
anim.SetBool("isJumping", true);
}
}
I just started to learn unity starting by following tutorials on YouTube. However I can't figure out why my jump animation is ending as soon as it starts on my first jump. On extra jumps it works fine. If you know how to fix this, pls help me.
In your update loop you call Jump which sets
anim.SetBool("isJumping", true);
and in your fixed update loop you have
anim.SetBool("isWalking", true);
So immediately after calling Jump on the next 'FixedUpdate' you are setting the animation bool of iswalking, unless moveInput is 0. I can't see all your code or what is happening to moveInput but I can tell you this is where your problem is. You need to change the animations of this code:
anim.SetBool("isWalking", true);
if (facingRight == false && moveInput>0)
{
flip();
}
else if (facingRight == true && moveInput < 0)
{
flip();
}
else if (moveInput == 0)
{
anim.SetBool("isWalking", false);
}

JumpCount resets immediately after jumping 2D platformer

I'm pretty new to all of this so sorry for rookie mistakes. I'm making a 2D platformer
I am checking for ground via RayCast and right after the player jumps, the jumpCounter resets to 0, so I get a bonus jump. I tried adding a 0.2s timer before it can reset but that caused trouble when jumping multiple times in a row (bunny hopping). Any help?
private void FixedUpdate()
{
GroundCheck();
if (state != State.hurt)
{
Movement();
DoubleJump();
StateMachine();
}
HurtCheck();
anim.SetInteger("state", (int)state);
}
private void Movement()
{
//Input.GetAxis returns a value between -1 up to 1
//Edit> Project Settings> Input> Axis> Horizontal
float hDirection = Input.GetAxisRaw("Horizontal");
//holding down "D" makes the value positive and vice versa
if (hDirection < 0)
{
rb.velocity = new Vector2(-speed, rb.velocity.y);
transform.localScale = new Vector2(-1, 1);
}
else if (hDirection > 0)
{
rb.velocity = new Vector2(speed, rb.velocity.y);
transform.localScale = new Vector2(1, 1);
}
else
{
}
if (Input.GetButtonDown("Jump") && isGrounded == true)
{
Jump();
}
}
private void Jump()
{
rb.velocity = new Vector2(rb.velocity.x, jumpforce);
state = State.jumping;
jumpCount += 1;
}
private void GroundCheck()
{
Debug.DrawRay(transform.position, Vector2.down * hitDistance, Color.green);
RaycastHit2D hit = Physics2D.Raycast(transform.position, Vector2.down, hitDistance, ground);
if(hit.collider != null)
{
isGrounded = true;
jumpCount = 0;
}
else
{
isGrounded = false;
}
}
private void DoubleJump()
{
if (Input.GetButtonDown("Jump") && isGrounded == false && jumpCount < 2)
{
rb.velocity = new Vector2(rb.velocity.x, jumpforce);
jumpCount += 1;
}
}
Hey Have you made sure your player's layer isn't ground layer or set ground layermask properly or maybe the hitDistance for the raycast is too high it should be very low like 0.1 or less or does jumpCount start from 0 or 1 try and alternate that or maybe have it start from two to lose the extra bonus jump...These would be where I would look, Good luck!

How to fix 2D animation while player walks?

I'm trying to make my character idle, run, jump and fall. I did it, but i have bug with runing animation. While he goes left or right, he doesn't play animation "run", which called by integer "noob" with parameter "2",he plays animation "fall", which "noob" is parameter "4"
I'm using Unity 4.5.x and C# code
using UnityEngine;
using System.Collections;
public class movement : MonoBehaviour {
Rigidbody2D rb;
Animator anim;
public int jumpCount = 0;
public Camera main;
float jumpTimer = 0;
void Start () {
rb = GetComponent<Rigidbody2D> ();
anim = GetComponent<Animator>();
}
void Update () {
if (Input.GetKeyDown (KeyCode.X) && jumpCount < 2 && jumpTimer == 0) {
jump ();
jumpCount += 1;
jumpTimer = 1;
StartCoroutine("jumpTime");
}
if (rb.velocity.y > 0) {
Flip();
anim.SetInteger ("noob", 3);
}
if (rb.velocity.y < 0) {
Flip();
anim.SetInteger ("noob", 4);
}
if (Input.GetAxis ("Horizontal") == 0 && rb.velocity.y == 0) {
anim.SetInteger ("noob", 1);
}
if (rb.velocity.y == 0 && Input.GetAxis ("Horizontal") != 0) {
Flip();
anim.SetInteger("noob", 2);
}
if (rb.velocity.y == 0) {
jumpCount = 0;
}
}
void FixedUpdate(){
rb.velocity = new Vector2 (Input.GetAxis ("Horizontal") * 12f, rb.velocity.y);
}
void jump(){
rb.AddForce (transform.up * 14F, ForceMode2D.Impulse);
}
void Flip() {
if (Input.GetAxis ("Horizontal") > 0) {
transform.localRotation = Quaternion.Euler (0, 0, 0);
}
if (Input.GetAxis ("Horizontal") < 0) {
transform.localRotation = Quaternion.Euler (0, 180, 0);
}
}
IEnumerator jumpTime() {
yield return new WaitForSeconds (0.4f);
jumpTimer = 0;
}
}
I tried to do something with jumCount, jumpTimer and velocity.y, but nothing helped
I would suggested making a grounded and jumping bool, you can use this bool to determine whether your character is airbourne. Also using else if conditional statements may help here to avoid setting your value more than once. Then you can do something like this:
if (grounded && jumping) {
Flip();
anim.SetInteger ("noob", 3);
jumping = false;
}
else if (!grounded) {
Flip();
anim.SetInteger ("noob", 4);
}
else if (Input.GetAxis ("Horizontal") == 0 && grounded) {
anim.SetInteger ("noob", 1);
}
else if (grounded && Input.GetAxis ("Horizontal") != 0) {
Flip();
anim.SetInteger("noob", 2);
}

Categories