- Home /
2D Wall Jumping
I'm developping a 2D platformer and i'm facing a little trouble. I'm actually trying to develop a Wall detection and the possibility to Wall Jump and go in the opposite direction. I'm able to detect Walls and when i press the jump button my player goes nuts. I actually made a little video to show you what's going on + my code :
Speed x 15 (on the code i only multiply the force on X by 15) = http://youtu.be/zeK8RTVQdiU
Normal Speed = http://youtu.be/GvW_x0hd7wk
Here is my code
#pragma strict var moveSpeed : float = 600; var jumpSpeed : float = 25; var fallSpeed : float = 64; var maxFallSpeed : float = 60; var maxUpSpeed : float = 25; var slopeLimit : float = 45; var onGround : boolean; var touchLeft : boolean; var touchRight : boolean; var justBounced : boolean; var contactAgainst : boolean;
private var vm : float;
private var xScale : float;
private var h : float;
private var v : float;
private var jump : boolean;
private var boxCollider : BoxCollider2D; //If boxCollider2D is used replace w/ ... private var boxColl : BoxCollider2D;
private var circleCollider : CircleCollider2D;
private var vectorRight : Vector2;
private var vectorLeft : Vector2;
function Start () {
xScale = transform.localScale.x;
boxCollider = GetComponent(BoxCollider2D);
circleCollider = GetComponent(CircleCollider2D);
var vectorLeft = Vector2(Vector3.left.x, Vector3.left.y);
var vectorRight = Vector2(Vector3.right.x, Vector3.right.y);
}
function Update () {
h = Input.GetAxisRaw("Horizontal"); //get horizontal input
v = Input.GetAxisRaw("Vertical"); //get vertical input
jump = Input.GetKey(KeyCode.Space); //get jump input
if((touchLeft || touchRight) && contactAgainst) {
var forceSaut : float;
if(touchLeft && !touchRight && jump) {
h = 1;
forceSaut = h * moveSpeed * Time.deltaTime;
Debug.Log(forceSaut);
rigidbody2D.AddForce(Vector2.right * forceSaut);
rigidbody2D.AddForce(Vector2.up * jumpSpeed);
justBounced = false;
}
else if(!touchLeft && touchRight && jump) {
h = -1;
forceSaut = h * moveSpeed * Time.deltaTime;
Debug.Log(forceSaut);
justBounced = true;
rigidbody2D.AddForce(Vector2.right * forceSaut * 15);
rigidbody2D.AddForce(Vector2.up * jumpSpeed * 3);
}
}
}
function FixedUpdate(){
if(onGround && jump && !touchLeft && !touchRight){ //Are we grounded can we jump?
vm = jumpSpeed;
}
if(justBounced)
h = 0;
var moveH : float = h * moveSpeed * Time.deltaTime; //Smooth horizontal movement
if(h < 0){
transform.localScale.x = -xScale;
} else if(h > 0){
transform.localScale.x = xScale;
}
rigidbody2D.AddForce(Vector2.right * moveH); //Apply horizontal movement
rigidbody2D.AddForce(Vector2.up * vm); //Apply vertical movement
vm -= fallSpeed * Time.deltaTime;
vm = Mathf.Clamp(vm, -maxFallSpeed, maxUpSpeed); //Clamp vertical speeds
rigidbody2D.velocity = Vector2.zero; //Stop movement if there is no input
onGround = touchLeft = touchRight = false;
checkPositionCollision();
}
function OnCollisionEnter2D(c : Collision2D){
CheckCollision(c);
}
function OnCollisionStay2D(c : Collision2D){
CheckCollision(c);
}
function OnCollisionExit2D(c : Collision2D) {
contactAgainst = false;
}
function CheckCollision(c : Collision2D){
for(var contact in c.contacts){
if(vm (inferior or egal) 0 && contact.point.y (inferior or egal) transform.position.y - ((circleCollider.radius * transform.localScale.y + transform.localScale.y) / 2) && Vector2.Angle(Vector2.up, contact.normal) (inferior or egal) slopeLimit){
onGround = true;
justBounced = false;
vm = Mathf.Max(0, vm);
contactAgainst = true;
}
} }
function checkPositionCollision() { var yCircle = transform.localPosition.y + (circleCollider.center.y transform.localScale.y); var circlePosition = Vector3(transform.localPosition.x , yCircle, transform.localPosition.z); var hitRight = Physics2D.Raycast(circlePosition, transform.right, circleCollider.radius transform.localScale.y + transform.localScale.y, 1 << LayerMask.NameToLayer("Walls")); var hitLeft = Physics2D.Raycast(circlePosition, -transform.right, circleCollider.radius * transform.localScale.y + transform.localScale.y, 1 << LayerMask.NameToLayer("Walls")); if(hitRight) { touchRight = true; justBounced = false; } if(hitLeft) { touchLeft = true; justBounced = false; } }
Thanks for your help :)
Done, it seems that it doesn't like the "<=" in the code section...
Answer by Kamigaku · Mar 24, 2014 at 11:22 AM
Well, i fixed it by myself, reworked completly the class. Here is my answer :
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour {
public bool onGround = false;
public bool jump = false;
public float maxSpeedX = 3f;
public float maxSpeedY = 3f;
public LayerMask whatIsGround;
public Transform groundChecker;
private float groundRadius = 0.1f;
private bool facingRight = true;
public bool touchLeft = false;
public bool touchRight = false;
private CircleCollider2D circleCollider;
public float velocityX;
public float velocityY;
void Start () {
circleCollider = GetComponent<CircleCollider2D>();
}
void FixedUpdate () {
float forceX = 0;
float forceY = 0;
velocityX = rigidbody2D.velocity.x;
velocityY = rigidbody2D.velocity.y;
//Je test si mon personnage est collé à un mur
checkWallPosition();
onGround = Physics2D.OverlapCircle (groundChecker.position, groundRadius, whatIsGround);
float moveH = Input.GetAxisRaw ("Horizontal");
jump = Input.GetButtonDown("Jump");
//Si je touche le sol
if (onGround) {
if(moveH != 0) {
forceX = maxSpeedX * moveH;
}
if(jump && !touchLeft && !touchRight) {
forceY = maxSpeedY;
}
else if(jump && (touchLeft || touchRight)) {
if(touchLeft) {
forceX = maxSpeedX;
}
else {
forceX = -maxSpeedX;
}
forceY = maxSpeedY;
Flip ();
}
else {
forceY = rigidbody2D.velocity.y;
}
}
//Si je ne touche pas le sol
else {
if(!jump && !touchLeft && !touchRight) {
forceY = rigidbody2D.velocity.y;
forceX = rigidbody2D.velocity.x;
}
else if(jump && (touchLeft || touchRight)) {
if(touchLeft) {
forceX = maxSpeedX;
if(!facingRight)
Flip ();
}
else {
forceX = -maxSpeedX;
if(facingRight)
Flip ();
}
forceY = maxSpeedY;
}
else if(touchLeft || touchRight) {
if(moveH == 0) {
forceX = 0;
forceY = rigidbody2D.velocity.y;
}
else {
if((touchLeft && moveH == -1) || (touchRight && moveH == 1)) {
if(moveH == -1 && facingRight) {
Flip ();
}
if(moveH == 1 && !facingRight) {
Flip ();
}
forceY = rigidbody2D.velocity.y / 3;
}
}
}
}
//Ici les forces sont appliquées
rigidbody2D.velocity = new Vector2 (forceX, forceY);
//Ici le personnage est retourné en fonction de sa position
if (onGround) {
if (moveH > 0 && !facingRight) {
Flip ();
}
else if (moveH < 0 && facingRight) {
Flip ();
}
}
}
private void Flip(){
facingRight = !facingRight;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
private void checkWallPosition() {
touchLeft = touchRight = false;
float yCircle = transform.localPosition.y + (circleCollider.center.y * transform.localScale.y);
Vector3 circlePosition = new Vector3(transform.localPosition.x , yCircle, transform.localPosition.z);
bool hitRight = Physics2D.Raycast(circlePosition, transform.right, circleCollider.radius * transform.localScale.y + transform.localScale.y, 1 << LayerMask.NameToLayer("Walls"));
bool hitLeft = Physics2D.Raycast(circlePosition, -transform.right, circleCollider.radius * transform.localScale.y + transform.localScale.y, 1 << LayerMask.NameToLayer("Walls"));
if(hitRight) {
touchRight = true;
}
if(hitLeft) {
touchLeft = true;
}
}
}
Your answer