Hi! I’m just starting out with Unity, and been reading up on several tutorials, and this site, although I’m not at all new to programming. The thing I’m trying to understand better right now is collisions.
I’ve seen the table of what collisions between objects send collision messages, and I’m trying to wrap my head around the when and how of it.
First of all, I know that rigidbodies are used for objects using physics, but it looks like it’s necessary for collision between two objects, as plain collider to collider doesn’t seem to detect collisions. Is that right, and if so, why is that?
And what about if I want to make a game entirely without physics at all (hypothetically)? Do I need to add a kinematic rigidbody to anything that moves?
And if my moving objects are all using rigidbodies, is there any reason that static objects (such as the level) would need it too? It doesn’t look like it’s mandatory, but is there any benefit to it (I assume from the help file that it’s more accurate?). And is there any downside or reason not to make everything a kinematic rigidbody (such as decreased performance?).
One reason I ask is because I want to program the collisions on my main character without using the character controller, such as situations where the capsule collision shape isn’t suitable for my character, or if I want more direct control over collisions.
I’ve had trouble finding good tutorials for character collision that isn’t based on either the character controller or using physics for collision handling, and every tutorial seems to use physics making it hard to know what is and isn’t related, so pardon the bombardment of questions.
Please correct me on any incorrect assumptions I have made here. I’ve read things that have said when to use each thing, but as a programmer it’s just as important to understand the why, and that’s the part I’m getting confused with.
That is a barrage of questions! All good – I’ll take a stab at a few of them.
At a very high level, use Collisions when you want near-perfect physics simulations, and Triggers when you just need to tell if two objects have/are/stopped touching. You’ll note that the OnCollision functions produce calculated and populated Collision objects, and the OnTrigger functions just give you Collider references. If you study the differences between those two classes, that will help give you insight as to when you’d want (or need) to use one or the other. Collisions, as you may expect and will see by the property set, are more computationally expensive.
Rigidbodies required for messages: you are correct – in order for a Collision or Trigger message to be raised as a result of two objects colliding, a rigidbody must be present on one of them. Two plain jane colliders will not raise a message for you. Why that is the case I don’t know for certain; it is how the underlying Ageia PhysX engine / Unity’s API was implemented. I would hazard a guess it is performance reasons since the physics engine is its own discrete processing loop, and this approach is opt-in rather than opt-out for colliders.
Game without physics, requiring Kinematic Rigidbodies on anything that moves: No, but the presence of a rigidbody will allow those objects to generate trigger messages, as when they bump into your level geometry that has Static Colliders defining the boundaries. The table you referenced in the beginning of your post is the end-all for what types of messages get generated based on the properties of the colliding objects.
Here’s a reply I posted to another user you may find useful, although it sounds like you have a decent understanding of everything just minus a few “Why” questions. The problem was how to keep a fish in a tank, and what combination of these objects to use. So I offered an answer with a Collision approach and a Trigger approach (near the bottom of the first page):
Thanks, that does clear up a lot, especially on triggers.
My main issue now is, according to that table, a rigidbody can’t send collision messages for collisions with static colliders (or other kinematic rigid bodies) once I set it to kinematic, which is the whole point for me. It says it can give me trigger messages, but then I’d have to set every other static collider to triggers, and I’m not sure how useful that would be for character movement and collision.
So is there a good way to control my character collision without needing to use the character collider? It seems Unity expects you to use it, and I’m having trouble finding the right solution. How did regular ol’ games deal with character collision without PhysX or a pre-built character collider? I’m looking into ray casting, but I’m not sure if that’s barking up the wrong tree for this collision situation.
Alright, I was having these same problems and questions.
Some have been answered here, but they are not the answer I was hoping to hear. Part of my game is using entirely unrealistic physics. It is far from hard to code, but I do not want to have to write my own detect collision functions just because I don’t want to use a rigid body. But how can I use a rigid body and turn off all of its physics?
I have some objects moving around with custom physics and I would like to be able to detect when they hit each other and static objects with colliders on them so I can affect them with code. But if they are rigid bodies, not only am I moving them in code, but the physics simulation is affecting it in all kinds of ways that I really don’t want it to.
What is the solution for this? I mean this seems like a common problem you would have in any arcade styled game.
Mark it isKinematic – however, I’m guessing you know that and that is actually causing other issues with your object collision behavior. To best answer both your questions, it would help if you’d post the bare bones details of your
Level Geometry
Primary (player?) Object you are moving around
Other objects
and explain at a high level how you want each to interact physically with all the others.
Last note, the CharacterController is a specialty/convenience class that gives you rigidbody-like collision detection without having to use a rigidbody. It solves some problems and introduces others depending on your usage scenario, so usage is where we should start for you guys and go from there.
Well, barebones, I’m working on something of a breakout clone. Its a bit more complicated than that, but not so far as the physics go. I’ve tried a few ways of getting the desired physics, but everything has had its own problems.
The game is still graphically 3d, but all the physics will be in 2D. The primary movers are the ball and paddle. I plan on having other movers later, however. Aside from that, there is just collision with static objects.
Desired physics is something like this: No gravity, no friction, no rotations. I would like the ball to inherit velocity from movers, such as the paddle. The paddles movement will only be controlled by input. At some point I will probably deal with vector addition for when the ball hits an uneven surface, but right now I just have horizontal and vertical surfaces, which I can just flip the x or y velocity on impact.
Pretty basic.
Kinematic rigid bodies may be the way to go. I think I messed with them for a short period of time, but I can’t recall.
Ok, after posting that, I made a quick test, and yeah, I think rigidbody kinematics is the way to go. I think the problem I had last time was that I was using OnCollisionEnter still, instead of OnTriggerEnter.
The only problem I can see might be detecting the direction of the collision. Do trigger events have that built in like collisions? Or will I have to like… check the difference between the two trigger objects positions to determine the direction?
I also might want to be able to find the normal direction of the face a mover collided with, can I do that with triggers?
I came up with the idea to raycast in the OnTriggerEvent, but I’m having some problems.
Here is the code:
var speed = 5.0;
var x = -1;
var y = 0;
var z = 0;
var objDir = Vector3(x,y,z);
var objVel = Vector3.zero;
function Update () {
var objVel = objDir * speed * Time.deltaTime;
transform.Translate(objVel);
}
function OnTriggerEnter(other : Collider){
var rayDir = Vector3.Normalize(Vector3.Scale(transform.position, other.attachedRigidbody.transform.position));
var hit : RaycastHit;
if (Physics.Raycast(transform.position, objDir, hit, 100.0)) {
print("Before "+objDir);
objDir = Vector3.Normalize(Vector3(objDir.x * hit.normal.x, objDir.y * hit.normal.y, 0));
print("After "+objDir);
print("Normal: "+hit.normal);
}
}
I don’t think I’m using the normal data from the hit properly. I don’t understand how Unity handles the Normal Vector exactly, so I’m not sure.
I don’t know what I’m doing wrong with this. I changed that script a little, but its roughly the same. I just don’t think the normal it is returning can be accurate. I am testing this with two spheres. One sphere is the mover, with this script attached. It moves in the negative x direction straight at the other sphere. For some reason it returns a normal something like : (-.6, 0, 0.8), which makes no sense. Its coming from the sphere, but it just doesn’t make sense that the normal of the object it collides with would be in a negative x direction when the object is moving in a negative x direction.
update
Upon further inspection, its because the ray is hitting the sphere from which I’m casting it. I don’t know how to stop it from doing that. The examples I looked at don’t even mention this as an issue.
#pragma strict
var speed = 5.0;
var x = -1.0;
var y = 0.0;
var z = 0.0;
var objDir = Vector3(x,y,z);
var objVel = Vector3.zero;
function Update () {
var objVel = objDir * speed * Time.deltaTime;
transform.Translate(objVel);
}
function OnTriggerEnter(other : Collider){
var ray = new Ray(transform.position, objDir);
var hit : RaycastHit;
if (other.collider.Raycast(ray, hit, 10.0)) {
if(hit.normal.x > 0) objDir.x *= -1;
if(hit.normal.y > 0) objDir.y *= -1;
objDir = Vector3.Normalize(Vector3((objDir.x + hit.normal.x)/2, (objDir.y + hit.normal.y)/2, 0));
}
}
I changed the way the ball reacts to the collision, but the biggest change here is that I cast the ray, but only look for the object that caused the trigger. Works great so far. If you want to handle your own physics, I think this is probably the easiest method to detect a collision and get the normals of it.
I’ve decided on programming my own collision, probably using a combination of a trigger collider and raycasting. Are there are good tutorials or references for working with raycasting? The help files are great for reference, but not so useful for learning it from scratch. The small bit I’ve managed to get working is copied from the one bit of sample code I could find, and stripped back until it did stuff.
At the moment I’ve just made a very simple demo where I can slide a box back and forth along some scaled boxes as platforms, and I have a script attached to the player box (a 1x2x1 box) that simply finds the ground and sits the box on the ground, but that’s about the extent of what I can do right now. All objects are using basic box colliders, no rigidbodies. Ignore the redundant code for handling the box positioning. I was just being lazy.
var hit : RaycastHit;
if(Physics.Raycast(transform.position, transform.up * -1.0, hit, 5)) {
//to offset the fact the ray starts from the center of a 2 unit tall box "character"
transform.position.y += 1.0;
//positions the box on the ground
transform.position.y -= hit.distance;
}
So are there any good tutorials for further learning raycasting?
In lieu of making a new post, I’ve run into some problems with my collision detection.
Its a breakout styled game, and I’m having problems with the ball traveling through objects from time to time. It happens a lot when it is moving fast. Trying to think of a good way to correct this. Here is the current collision code:
function OnTriggerEnter(other : Collider){
var ray = new Ray(transform.position, objDir);
var hit : RaycastHit;
if (other.collider.Raycast(ray, hit, 10.0)) {
collision(hit);//This just handles the actual collision, but the problem occurs when this is not called at all.
}
}
I’m thinking that maybe it is moving too fast for the OnTriggerEvent to trigger. However, it also happens in the corners a lot as well, which doesn’t seem to be a speed problem.
edit
Did a bit of error testing and I’ve found that the trigger is being called but the Ray is missing the object which the ball collides with. Which is not good, as I need the Normal data from the raycast to handle collisions.
I’m just giving this a bump because I’m still lost as to how to achieve any sort of good collision in Unity without resorting to the character collider, which I won’t use.
I’m making a simple 2D platformer. I need character collision so my character stops at walls, doesn’t jump through the roof, or fall through the floor. My level blocks use box/mesh colliders (depending on the block), but don’t use rigidbodies, as they don’t move.
I would like my character to use a combination of a box collider for simple collision with enemies, and the level, then use raycasting to place his feet accurately on the ground and detect the ground angle. The raycasting part I already have working fine. At the moment I’m only using one ray, but depending on how I implement the rest of the collision, I may have two rays for the front and back to cover the width better.
The problem is that the only other thing besides the character collider that will detect collisions with non-rigibodies (according to the collision matrix) is non-kinematic rigid bodies, but I am not controlling my character using physics AT ALL. I’m making a very basic 2D platformer. Kinematic rigidbodies can be used as triggers, but for collisions with the level I can’t think of any way that a trigger can give me any decent information to create a good movement system (if I’m wrong about that, I’d love to hear more info).
Using raycasting for all of my collision seems excessive and not a good solution for the situation (unless there’s some trick I’m not thinking of). Projecting rays sidewards for wall collision won’t work well, because a thin moving platform could easily fall through a gap unless I have many rays, which seems a bit expensive and messy. And I thought about situations where I project a ray vertically and see what crosses the path, but then I get no info about how far it’s penetrating.
So how do people create usable collision in Unity without physics and without being forced into the character collider?
I’m doing a similar breakout type game and I’ve experienced that behavior of things passing through my triggers. Reason is because it is using the rigidbodies calculations (I’m using OnTriggerEnter too) and if the object is moving too fast then the negative force isn’t enough to reverse its direction so it passes directly through the trigger. I can balance this okay for my ball because the velocity of the ball can be more easily manipulated and it should always be in motion, but I’m having trouble with keeping the paddle in the level bounds.
The paddle uses the mouse X axis for movement and if I ram into the wall really fast it just goes right through it. If I hit the paddle into the wall softly it works as intended. I tried making a buffer that was before the wall to slow the paddle down, but that doesn’t work. I tried reversing the transform.position by doing transform.position += transform.position, but that doesn’t work. I tried to set velocity to 0 when the paddle position was changing (as the mouse was being moved), but that didn’t work. I also tried to Clamp the transform.position of the paddle when it hit the wall trigger. The wall is made out of a plane. Any ideas?
Setup is:
Wall = plane with mesh collider (tried with isTrigger set and not set it reacts the same)
paddle = rigidbody and box collider. Set to kinematic and isTrigger.
The plane has a script that OnTriggerEnter () {Sends a message}
and the paddle has the function by the same name as the message which does this:
transform.position.x = Mathf.Clamp(7, 7, 7);
The message is being sent. I’ve put a print(something) in there and it shows up. It also works as long as I move the paddle into the wall at a slow pace. It’s when I ram it into the wall, it doesn’t clamp at 7 which is where I want it to stop.
Everything in Unity that moves pretty much should be a rigidbody. If you want it to collide, it must also be a non-kinematic rigidbody (Kinematic rigidbodies can stop moving objects, but when they move nothing can stop them).
I however, tend to keep a very tight grip on my rigidbodies. I’ll manually set the velocity and rotation (with Freeze Rotation, of course) no matter how many times the Unity docs tell me to use AddForce instead.
That didn’t work. My paddle is default layer so I put layer mask to everything except default layer. I also tried various skin lengths, but none worked.
Ah, yes. I overlooked something in your post. As dallon pointed out, if you want collision, you will need to use a normal non-kinematic rigidbody and move it with forces or velocity.
If you do not want to use forces or velocity (for whatever reasons) and need to set the position directly, your only option is to use a character controller instead of a rigidbody.