I’m making a simple platfomer using the script in the 2D gameplay tutorial to help me out. I’ve gotten pretty far, but I can’t figure out how to make the character bounce when they hit a platform. The character isn’t a rigidbody, so I’m not really sure what route to take.
I’m pretty new to this so sorry if this is a stupid question
If you are calculating decent in math. Say you have a current downward velocity of 5 units, so you do a Physics.Raycast from the bottom of the character to the ground surface, and you find out that you only require 3 units to get there, then you would have a remainder of 2 units, which would then mean that instead of going down 5 units, or 3 (which would be required to hit the ground) you only do 2, and change your vertical motion from -5 (down) to 2 (up). Apply gravity to that next go around and you get “bounce”
No need to be ray-casting for this, seriously guys this is basic stuff. It’s all explained in the article I linked to.
You have controller velocity V and collision normal (normal of contact plane) N. This combined with the OnControllerColliderHit hook gives us everything we need to calculate the response.
Basic physics collision response can be obtained with:
Vn = Dot(V,N) * N; // Velocity normal to collision plane
Vt = V-Vn; // Perpendicular to collision plane in direction of velocity
bounceVector = Vt - (Vn*Kr);
Kr is the coefficient of restitution. At 1.0 you get a fully elastic collision (will bounce as high as it falls). At 0 you get a totally static response (sticks to plane on collision). Of course you can also apply separate coefficients to each vector if you want more control over the response.
How you integrate that bounce vector into the overall movement is up to you. No doubt you’ll also need to be selective about which collisions you actually calculate the bounce for, you probably don’t want to be bouncing off all the walls and rigid bodies in a scene.
Example character controller in C# that uses the above pseudo-code below. I just grabbed the move exmaple code form the manual here: Unity - Scripting API: CharacterController.Move and added in the OnControllerColliderHit to caculate/store the collision/bounce response then a another few lines to integrate that response into the update loop.
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(CharacterController))]
public class Character : MonoBehaviour {
public float speed = 6.0F;
public float jumpSpeed = 8.0F;
public float gravity = 20.0F;
private Vector3 moveDirection = Vector3.zero;
private Vector3 bounce = Vector3.zero;
void Update() {
CharacterController controller = GetComponent<CharacterController>();
if (controller.isGrounded) {
if (bounce.sqrMagnitude > 0) {
moveDirection = bounce;
bounce = Vector3.zero;
} else {
moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
moveDirection = transform.TransformDirection(moveDirection);
moveDirection *= speed;
}
if (Input.GetButton("Jump"))
moveDirection.y = jumpSpeed;
}
moveDirection.y -= gravity * Time.deltaTime;
controller.Move(moveDirection * Time.deltaTime);
}
void OnControllerColliderHit(ControllerColliderHit hit) {
Rigidbody body = hit.collider.attachedRigidbody;
// Only bounce on static objects...
if ((body == null || body.isKinematic) hit.controller.velocity.y < -1f) {
float kr = 0.5f;
Vector3 v = hit.controller.velocity;
Vector3 n = hit.normal;
Vector3 vn = Vector3.Dot(v,n) * n;
Vector3 vt = v - vn;
bounce = vt -(vn*kr);
}
}
void OnDrawGizmos() {
Debug.DrawLine(transform.position, transform.position + controller.velocity, Color.red);
Debug.DrawLine(transform.position, transform.position + bounce, Color.green);
}
}