- Home /
Custom Collision Detection
Okay, I am trying to make my own character controller based completely on script with no help form unity's pre-built components. Right now to detect collision's I have a ray casting from the controller on each of the sides (front,back,left,right). That part is working fine but my problem is getting the object to stop when its going to go through an object. Well that's not exactly correct, I am getting the controller to stop by setting the speed variable to 0. The real problem is getting it to go again. What happens is the controller stops but there's no way to get away from the wall or object after a collision has occurred. So my question is what would be the best way to fix this problem.
By the way I am using unity script not c# just in case anyone decides to setup a code snippet.
Thanks in advance and sorry for the lengthy question.
Answer by lil_billy · May 12, 2011 at 06:22 PM
dear god that sounds tricky so id recommend not using raycasts because they are expensive on processing but if you are determined to go that way
now this isnt accurate so you'll have to figure out the right numbers you could write it so if right raycast hits object, move player in the negative x if left move in positve x ir front move in negative z if back move in positve z
nothing dramatic just enough to push the player away from the object and get his raycast out of it at that rate you could even set it to apply damage if they are touched
but if you use colliders than you wont have to worry about any of this because well colliders collide and either depending on your preference will stop objects from passing through each other or not.
Thanks for your thoughts. I did think of something similar to this but was hoping there was a better way. I think I'm just going to bite the bullet though and figure out how to set this up. Again thanks for your help.
Wait wait wait! You're talking about raycasts like they can tell you when two things bump together. This is NOT what they are for! You can do a raycast and check the distance from the beginning of the ray to the impact point but that is just absolutely ridiculous.
This may not be what they are for but I was not asking if that's what they are for. I'm not new to unity or game development. I have in pointed fact been working in game development for years now. I simply wanted to see if it could be done, and it can. It obviously has multiple issues but works better then I had anticipated. I will be putting up a link to a webplayer version of what I created as proof of concept. It uses only raycasts for all collision detection.
yeah i mean he was asking about raycasts so thats why i discussed it, the glory of raycasts is they detect practically everything which trigger colliders dont do. and with that you can program it so that your object moves the ray away from what it touches so yeah you could make it behave like a collider. now i did briefly mention that this is probably not a good use for them since colliders are more efficient and already do this job. But again he asked if it were possible. @Flavi, dont limit yourself to the face value of any of the operations, the beauty of unity is that it can be used for any
Answer by flaviusxvii · May 12, 2011 at 06:00 PM
Why are you using raycasting and not the actual collision detection provided via PhysX?
What do you do when you run into a wall? Either back up or turn you silly person.
That does not work because it checks to see if there is a collision on all sides of the controller and once the controller has detected a collision it has already set the speed to 0 so it can no longer move. $$anonymous$$y reason for attempting this is pretty much just for the experience. Later I want to build a very comprehensive character control rig and I've found the best way to go about anything is to start from scratch. Probably does sound silly with the very well done collision system already in unity but I would very much like to have the knowledge required to build such a rig.
It has taken a lot of people many years to build PhysX, and collision detection is a small part of it. Not to mention raycasting isn't typically involved in collision detection at all (except for fast moving objects). So I'm not sure you're even learning anything useful. To top it all off, I guess I don't understand your original question at all.
Answer by themusicdork · Dec 27, 2011 at 09:03 AM
Use Physics.Linecast?. If nested within a while statement it should work. In english cause I am lazy. While there is a collision if I move{ moveless; } else{ DO OTHER STUFF; }
Linecasting only checks a certain distance. So as long as your speed is at zero it should not return a collision. Cheers.
Answer by Matt-Downey · Jun 17, 2012 at 04:35 AM
What you are looking for is the Dot product.
You want to disable movement when the player is inside a wall, so
if(Vector3.Dot(velocity,hit.normal) < -0.1) velocity = Vector3.zero; //when you get better replace this with a custom-made collision function, which will nullify the component of the velocity towards the wall
It would be easier for you to use one raycast in the direction you are moving.
In order to do this you will have to use transform.forward for the direction of the raycast. If you really want to create a capable-of-working-in-any-situation collision system your knowledge of Vector3's should be impeccable (you should eventually know the concepts of the Dot Product, Cross Product, Vector Projection, Vector Rejection, Vector Reflection).
For said raycast, look into this code will help:
var hit : RaycastHit;
var hit2 : RaycastHit;
if(Physics.Raycast(pos - Vector3.up*0.5,dir,hit,Mathf.Infinity,(1 << 0))
&& Physics.Raycast(pos - Vector3.up*0.5,-hit.normal,hit2,Mathf.Infinity, (1 << 0))
&& (hit.distance < radius + dist || hit2.distance < radius + dist))//find the normal below us and find how close it is
{
if(hit.distance > hit2.distance)
{
hit.distance = hit2.distance - radius;
}
else hit.distance -= radius;
}
return hit;
(I call this IterationArray.)
It basically finds the first normal in the direction the direction of the velocity, then takes that normal and finds how close it is. You should optimize this even more by using some logic like this:
if(Physics.Check Capsule) //if there is something occupying the space, then do stuff, otherwise don't bother
{
if(IterationArray) //check if we are on a flat plane first
else if(Physics.SphereCast) //check for a contour or corner of a mesh
}
I'm currently making a parkour package that I'll put up on the Unity Asset Server for free, so when I get there, I'll try to inform you. The parkour package has a pre-collision system with a failsafe of the Unity3D collision system that prevents bad things from happening. In the OnCollisionStay field, a Debug.Log() is rarely called, meaning that the precollisions work most of the time (but definitely not all of the time).
just realised the dot product code I mentioned will work with your code as it is now, you just need to keep in $$anonymous$$d that you should upgrade to more complex stuff when you get the chance. Currently you have to run that line of code four times, which is no fun.