- Home /
Question by
asdfman123 · Oct 10, 2013 at 08:41 PM ·
collisionraycasting
Help with raycasting collision detection.
I was playing around with this c# script for collision detection in a side scroller game. It only detected collisions on the Y, axis so i decided to modify it, to make it detect collisions along the x axis, and currently the collisions will only work if you are stopped a short distance from the object you're colliding with, and then collide with it. Here is the code for the collision detection: using UnityEngine; using System.Collections;
[RequireComponent (typeof(BoxCollider))]
public class PlayerPhysics : MonoBehaviour {
public LayerMask collisionMask;
private BoxCollider collider;
private Vector3 s;
private Vector3 c;
private float skin = .005f;
[HideInInspector]
public bool grounded;
Ray Yray;
RaycastHit Yhit;
Ray Xray;
RaycastHit Xhit;
void Start() {
collider = GetComponent<BoxCollider>();
s = collider.size;
c = collider.center;
}
void Update()
{
s = collider.size;
c = collider.center;
}
public void Move(Vector2 moveAmount) {
float deltaY = moveAmount.y;
float deltaX = moveAmount.x;
Vector2 p = transform.position;
// Check collisions above and below
grounded = false;
for (int i = 0; i<3; i ++) {
float dir = Mathf.Sign(deltaY);
float x = (p.x + c.x - s.x/2) + s.x/2 * i; // Left, centre and then rightmost point of collider
float y = p.y + c.y + s.y/2 * dir; // Bottom of collider
Yray = new Ray(new Vector2(x,y), new Vector2(0,dir));
Debug.DrawRay(Yray.origin,Yray.direction);
if (Physics.Raycast(Yray,out Yhit,Mathf.Abs(deltaY), collisionMask)) {
// Get Distance between player and ground
float dst = Vector3.Distance (Yray.origin, Yhit.point);
// Stop player's downwards movement after coming within skin width of a collider
if (dst > skin) {
deltaY = dst * dir + skin;
}
else {
deltaY = 0;
}
grounded = true;
break;
}
}
for (int i = 0; i<3; i ++) {
float dir = Mathf.Sign(deltaX);
float x = p.x + c.x + s.x/2 * dir;//Right of the collider
float y = (p.y + c.y - s.y/2) + s.y/2 * i;// Top, middle, and bottom of the collider.
Xray = new Ray(new Vector2(x,y), new Vector2(dir, 0));
Debug.DrawRay(Xray.origin, Xray.direction);
Debug.DrawLine(Xray.origin, Xhit.point);
float rng = Mathf.Abs((deltaX == 0)? 0.005f:deltaX);
Debug.Log(rng);
if (Physics.Raycast(Xray,out Xhit, Mathf.Abs(deltaX),collisionMask)) {
// Get Distance between player and object infront of him.
float dst = Vector3.Distance (Xray.origin, Xhit.point);
// Stop player's horizontal movement after coming within skin width of a collider
if (dst > skin) {
deltaX = dst * dir + skin;
}
else {
deltaX = 0;
}
break;
}
}
Vector2 finalTransform = new Vector2(deltaX,deltaY);
transform.Translate(finalTransform);
}
}
And here is the code calling that:
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(PlayerPhysics))]
public class PlayerController : MonoBehaviour {
// Player Handling
public float gravity = 20;
public float speed = 8;
public float acceleration = 30;
public float jumpHeight = 12;
private float currentSpeed;
private float targetSpeed;
private Vector2 amountToMove;
private PlayerPhysics playerPhysics;
BoxCollider boxCollider;
void Start () {
boxCollider = GetComponent<BoxCollider>();
playerPhysics = GetComponent<PlayerPhysics>();
}
void Update () {
targetSpeed = Input.GetAxisRaw("Horizontal") * speed;
currentSpeed = IncrementTowards(currentSpeed, targetSpeed,acceleration);
if (playerPhysics.grounded) {
amountToMove.y = 0;
// Jump
if (Input.GetButtonDown("Jump")) {
amountToMove.y = jumpHeight;
}
}
//Crouch
if (Input.GetKeyDown(KeyCode.LeftShift))
{
transform.localScale -= new Vector3(0, transform.localScale.y/2, 0);
boxCollider.size -= new Vector3(0, boxCollider.size.y/2, 0);
}
//Uncrouch
if (Input.GetKeyUp(KeyCode.LeftShift))
{
transform.position += new Vector3(0, 1, 0);
transform.localScale += new Vector3(0, transform.localScale.y, 0);
boxCollider.size += new Vector3(0, boxCollider.size.y, 0);
}
amountToMove.x = currentSpeed;
amountToMove.y -= gravity * Time.deltaTime;
playerPhysics.Move(amountToMove * Time.deltaTime);
}
// Increase n towards target by speed
private float IncrementTowards(float n, float target, float a) {
if (n == target) {
return n;
}
else {
float dir = Mathf.Sign(target - n); // must n be increased or decreased to get closer to target
n += a * Time.deltaTime * dir;
return (dir == Mathf.Sign(target-n))? n: target; // if n has now passed target then return target, otherwise return n
}
}
}
Please forgive me, as I'm a unity newbie.
Comment
Your answer
