Hi!, I'm currently working on a 2D platformer game. It's similar to super meat boy . I'm currently struggling with the Wall Jump, actually it works but you can jump straight up in the Y direction, and I want to when you try to jump from the wall you get pushed a bit to the opposite direction so you can't go straight up, similar what you feel in Super meat boy, thi is what I have: This is the code for the gravity because I'm using a Kinematic type Rigidbody2D. Code (CSharp): using System.Collections; using System.Collections.Generic; using UnityEngine; public class PhysicsObject : MonoBehaviour { public float minGroundNormalY = .65f; public float gravityModifier = 1f; protected Vector2 targetVelocity; protected bool grounded; protected Vector2 groundNormal; protected BoxCollider2D col2D; protected Rigidbody2D rb2d; protected Vector2 velocity; protected ContactFilter2D contactFilter; protected RaycastHit2D[] hitBuffer = new RaycastHit2D[16]; protected List<RaycastHit2D>hitBufferList = new List<RaycastHit2D> (16); protected const float minMoveDistance = 0.001f; protected const float shellRadius = 0.01f; void OnEnable() { col2D = GetComponent<BoxCollider2D> (); rb2d = GetComponent<Rigidbody2D> (); } // Use this for initialization void Start () { contactFilter.useTriggers = false; contactFilter.SetLayerMask (Physics2D.GetLayerCollisionMask (gameObject.layer)); contactFilter.useLayerMask = true; } // Update is called once per frame void Update () { targetVelocity = Vector2.zero; ComputeVelocity (); } protected virtual void ComputeVelocity(){ } void FixedUpdate() { if (Input.GetButtonUp ("Grab")) { gravityModifier = 1f; } velocity += gravityModifier * Physics2D.gravity * Time.deltaTime; velocity.x = targetVelocity.x; grounded = false; Vector2 deltaPosition = velocity * Time.deltaTime; Vector2 moveAlongGround = new Vector2 (groundNormal.y, -groundNormal.x); Vector2 move = moveAlongGround * deltaPosition.x; Movement (move, false); move = Vector2.up * deltaPosition.y; Movement (move, true); } void Movement(Vector2 move, bool yMovement) { float distance = move.magnitude; if (distance > minMoveDistance) { int count = rb2d.Cast (move, contactFilter, hitBuffer, distance + shellRadius); hitBufferList.Clear (); for (int i = 0; i < count; i++) { hitBufferList.Add (hitBuffer [i]); } for (int i = 0; i < hitBufferList.Count; i++) { Vector2 currentNormal = hitBufferList [i].normal; if (currentNormal.y > minGroundNormalY) { grounded = true; if (yMovement) { groundNormal = currentNormal; currentNormal.x = 0; } } float projection = Vector2.Dot (velocity, currentNormal); if (projection < 0) { velocity = velocity - projection * currentNormal; } float modifiedDistance = hitBufferList [i].distance - shellRadius; distance = modifiedDistance < distance ? modifiedDistance : distance; } } rb2d.position = rb2d.position + move.normalized * distance; } } And this is the player controller: Code (CSharp): using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerPlatformerController : PhysicsObject { public float maxSpeed = 7f; public float jumpTakeOffSpeed = 7f; public bool grabbed; public bool crouched; public bool running; public bool sliding; public bool facingRight; public bool checkSlide = false; private bool used; public Vector2 speed = new Vector2(2,2); private SpriteRenderer spriteRenderer; private Animator animator; // Use this for initialization void Awake () { spriteRenderer = GetComponent<SpriteRenderer> (); animator = GetComponent<Animator> (); } protected override void ComputeVelocity() { Vector2 move = Vector2.zero; // Movimiento personaje if (!crouched) { if (sliding) { // Comprobar en que direccion se esta moviendo if (!checkSlide) { move.x = Input.GetAxis ("Horizontal") ; if (move.x < 0.01) { facingRight = false; } else if (move.x > 0.01) { facingRight = true; } checkSlide = true; } // Si se mueve hacia la izquierda if (!facingRight) { move.x = Input.GetAxis ("Horizontal"); if (move.x < 0.01) { move.x = Input.GetAxis ("Horizontal") * 1.5f; } else if (move.x > 0.01) { move.x = 0; } } // Si se mueve hacia la derecha else if (facingRight) { move.x = Input.GetAxis ("Horizontal"); if (move.x < 0.01) { move.x = 0; } else if (move.x > 0.01) { move.x = Input.GetAxis ("Horizontal") * 1.5f; } } } else { if (Input.GetButton ("Run") && grounded) { move.x = Input.GetAxis ("Horizontal") * 1.5f; running = true; animator.SetBool ("running", running); } else { move.x = Input.GetAxis ("Horizontal"); running = false; animator.SetBool ("running", running); } } } // Finaliza movimiento if (Input.GetButtonDown ("Crouch") && grounded && !running) { used = true; crouched = true; animator.SetBool ("crouch", crouched); col2D.size = new Vector2(col2D.size.x, col2D.size.y * 0.5f); col2D.offset = new Vector2(col2D.offset.x, col2D.offset.y - 0.12f); } if (Input.GetButtonUp ("Crouch") && used) { used = false; crouched = false; animator.SetBool ("crouch", crouched); col2D.size = new Vector2(col2D.size.x, col2D.size.y * 2f); col2D.offset = new Vector2(col2D.offset.x, 0); } if (Input.GetButtonDown ("Jump") && running && grounded) { animator.SetBool ("slide", true); col2D.size = new Vector2(col2D.size.x, col2D.size.y * 0.5f); col2D.offset = new Vector2(col2D.offset.x, col2D.offset.y - 0.12f); sliding = true; StartCoroutine (Slide()); } if (Input.GetButtonDown ("Jump") && grounded && !crouched && !running) { velocity.y = jumpTakeOffSpeed; } else if (Input.GetButtonUp ("Jump")) { if (velocity.y > 0) { velocity.y = velocity.y * .5f; } } if (Input.GetButtonDown ("Jump") && grabbed) { velocity.y = jumpTakeOffSpeed; } bool fliSprite = (spriteRenderer.flipX ? (move.x > 0.01f) : (move.x < 0.01f)); if (fliSprite) { spriteRenderer.flipX = !spriteRenderer.flipX; } animator.SetBool ("grabbed", grabbed); animator.SetBool ("grounded", grounded); animator.SetFloat ("velocityX", Mathf.Abs (velocity.x) / maxSpeed); if (!grabbed) { targetVelocity = move * maxSpeed; } } void OnTriggerEnter2D (Collider2D col) { if (col.tag == "Climb" && Input.GetButton ("Grab")) { velocity.y = 0; gravityModifier = 0.1f; grabbed = true; } } void OnTriggerExit2D (Collider2D col) { if (col.tag == "Climb") { gravityModifier = 1f; grabbed = false; } } IEnumerator Slide() { yield return new WaitForSeconds (0.5f); animator.SetBool ("slide", false); col2D.size = new Vector2(col2D.size.x, col2D.size.y * 2f); col2D.offset = new Vector2(col2D.offset.x, 0); sliding = false; checkSlide = false; } IEnumerator Kinematic() { yield return new WaitForSeconds (0.1f); rb2d.isKinematic = true; } } As you can see the code to jump from the wall is on line 124, I tried with rb2d.AddForce but it wont work because of the kinematic rigidbody. Appreciate so much the help, had been struggling for hours with this
Hey dude, looks like you just need to be pointed to a new vocabulary term for what you're looking to do. I believe the term of what you're looking for is Lerp. If this ends up being too rigid looking then you may need to get into a Slerp function which is slower but more in tune with multiple interactions than raw value forces applied. https://docs.unity3d.com/ScriptReference/Mathf.Lerp.html hope this sends you in the right direction.