- Home /
problem with 2d movement down slopes
I´m making a 2d platformer with a character that can go up and down on slopes.
The character have 3 differents colliders, that form a capsule together. 2 sphere colliders and one rectangle collider. (Similar to unity character controller that can detect collisions on sides, below and above)
Character Colliders
The lower sphere collider is used for detect collisions with objects below the player and return a "isGround" boolean. Until here it works well.
The same lowest sphere collider is used for detect the normal of the object below. For achieve it I´m using the function getContacts with the collider, then a get the normal (contact.normal) and rotate it -90 degrees in +Z axis (forward). The rotation is necessary because of .normal return a vector in upward direction.
If the collision below have an angle of 45 degrees, the script return a vector2 "horizontalNormal" in the direction of the slope below. That also works properly, I draw a line on gizmos in the horizontalNormal direction and it seems to be correct.
White line represent horizontal movement normal
The problem
the problem is that the character is still bouncing when going down slopes, despite I´m applying the horizontal movement in the horizontalNormal direction.
My code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class playerScript : MonoBehaviour
{
//variables
public bool doubleJump;
public bool pistol;
//physics
Rigidbody2D phy;
public Collider2D belowCollision;
bool isGrounded;
int canJump;
public float jump = 14;
public float acceleration = 50;
public float speed = 3;
public float speedSprint = 6;
public float friction = 50;
public float gravity = 10;
public float maxGravity = 18;
bool getDown;
public float jumpCooldown;
public bool jumping;
Vector2 horizontalNormal = Vector2.right;
//animation
SpriteRenderer sprite;
Animator animator;
private void Start()
{
phy = GetComponent<Rigidbody2D>();
sprite = GetComponent<SpriteRenderer>();
animator = GetComponent<Animator>();
Physics2D.IgnoreCollision(this.gameObject.GetComponent<CircleCollider2D>(), belowCollision.GetComponent<Collider2D>());
Physics2D.IgnoreCollision(this.gameObject.GetComponent<BoxCollider2D>(), belowCollision.GetComponent<Collider2D>());
Physics2D.IgnoreCollision(this.gameObject.GetComponent<BoxCollider2D>(), this.gameObject.GetComponent<CircleCollider2D>());
}
private void Update()
{
//check jump
if (Input.GetButtonDown("Jump") && canJump > 0) StartCoroutine(Jump());
//update animation speed
//animator.SetFloat("speed", Mathf.Abs(hspeed / 10));
if (Input.GetAxis("Horizontal") < 0)
{
sprite.flipX = true;
}
else
{
if (Input.GetAxis("Horizontal") > 0)
{
sprite.flipX = false;
}
}
//update animations
float vel = speed;
if (Input.GetButton("Run"))
{
vel = speedSprint;
}
if (Input.GetAxis("Horizontal") == 0)
{
if (animator.GetFloat("speed") > 0 + friction * Time.deltaTime) { animator.SetFloat("speed", animator.GetFloat("speed") - friction * Time.deltaTime); }
else { animator.SetFloat("speed", 0); }
}
else
{
if (animator.GetFloat("speed") < vel - acceleration * Time.deltaTime) { animator.SetFloat("speed", animator.GetFloat("speed") + acceleration * Time.deltaTime); }
else { animator.SetFloat("speed", vel); }
}
if (isGrounded == true)
{
transform.rotation = Quaternion.Euler(0, 0, Vector3.SignedAngle(Vector3.right, Vector2.right, Vector3.forward)); //replace "Vector2.right" with ramp direction vector
}
else
{
transform.rotation = Quaternion.identity;
}
}
private void FixedUpdate()
{
//CHECK FLOOR
ContactPoint2D[] collisions = new ContactPoint2D[1];
if (belowCollision.GetContacts(collisions) > 0)
{
isGrounded = true;
if (!jumping)
{
canJump = 1;
if (doubleJump) canJump = 2;
}
horizontalNormal = Quaternion.AngleAxis(-90,Vector3.forward) * collisions[0].normal;
}
else
{
isGrounded = false;
horizontalNormal = Vector2.right;
}
//if grounded stop falling
if (isGrounded == true && phy.velocity.y < 0) { phy.velocity = new Vector2(phy.velocity.x, 0); };
//get down on platforms
if (Input.GetAxis("Vertical") < 0) { getDown = true; } else { getDown = false; }
//apply movements
float vel = speed;
if (Input.GetButton("Run")) vel = speedSprint;
if (Input.GetAxis("Horizontal") > 0 && phy.velocity.x < vel)
{
phy.velocity += horizontalNormal * acceleration * Time.deltaTime;
}
if (Input.GetAxis("Horizontal") < 0 && phy.velocity.x > -vel)
{
phy.velocity -= horizontalNormal * acceleration * Time.deltaTime;
}
// h friction
if (Input.GetAxis("Horizontal") == 0)
{
if (Mathf.Abs(phy.velocity.x) > friction * Time.deltaTime)
{ phy.velocity -= Mathf.Sign(phy.velocity.x) * horizontalNormal * friction * Time.deltaTime; } //replace "Vector2.right" with ramp direction vector
else
{ phy.velocity = new Vector2(0, phy.velocity.y); }
}
//gravity
if (phy.velocity.y > -maxGravity && isGrounded == false) { phy.velocity += Vector2.down * gravity * Time.deltaTime; }
}
IEnumerator Jump()
{
phy.velocity = new Vector2(phy.velocity.x, jump);
Vector2 pos = transform.position;
canJump--;
jumping = true;
yield return new WaitForSeconds(jumpCooldown);
jumping = false;
}
private void OnDrawGizmos()
{
Vector3 normal = horizontalNormal;
Gizmos.DrawLine(transform.position, transform.position + normal);
}
}
Your answer
Follow this Question
Related Questions
Bounce into the air 1 Answer
How to make my character stop stuttering when walking down a slope? 2 Answers
Rigidbody2D character movement problem 0 Answers
Rigidbody2D jumping off of slopes 0 Answers