Unity ignore collisions on the same layer - unity3d

I want to use Physics.IgnoreCollision to avoid bullets hitting themselves.
The bullets are spawned on layer 8. Why is this not working? How can you ignore collisions with everything on the same layer?
// bulletscript.cs
gameObject.layer = 8;
// maingamescript.cs
Physics.IgnoreCollision(8,8);
There may also be other objects on layer 8 that should also be ignored.
(for example, the player ship).

Why not use the handy dandy Physics Manager. Go to Edit->Project Settings-> Physics and set up the proper layer collisions.

Go to Physics Manager and un-check the layer with itself to avoid collision.

Troubleshot:
Unity bug, try to update to latest Unity 5.3.x (5.4 currently has nasty bugs)
Make sure the bullets and players are effectively in the wanted layer
The change in layer takes some time to take effect (few frames), since bullet are fast, you are probably encurring in that lag (so in the time the change take effect the bullet already hitted the target)
The best way is to have a Bullet Prefab that is spawned already in the correct layer, you can later customize that by changin graphics at runtime if you like, but to avoid the lag it should be instantiated already in the correct layer.
There is no need to go to physics manager, the OP already do the correct code equivalent to the physics manager. The real problem is that the GameObject should be already instantiated with the correct layer, because layer update may take some time to get effective.
Another workaround is to disable/reenable the collider.

Related

Recommended strategy for overriding certain Rigidbody collisions in Unity?

I'm looking for a little newbie advice on gamedev strategy and/or approach. I'm working on a game that uses Rigidbody physics in Unity and I've got a character interacting nicely with physical objects in the game world. The thing I'm trying to work through is that there are certain physical interactions that I want to control, but my own attempts to control them are conflicting with what Unity is already (correctly) doing.
For simplicity, let's just say I've got a Rigidbody-based player, and when certain Rigidbody-based objects collide with that player, I want to override where they deflect to. When I detect the collision and apply my own force with rb.AddForce(myForceVector, ForceMode.VelocityChange), Unity is also applying it's own force as a result of the same collision. I also tried setting the velocity directly with rb.velocity = myForceVector, which mostly works, but there are still situations where Unity applies force after I set the velocity so it's glitchy at best.
Other options I've considered are:
Use an additional, larger IsTrigger collision mesh to detect and handler the special type of collision I'm looking for before the actual collision occurs. That might work for slower speed projectiles, but likely will have the same issue for faster collisions.
Change the player to not being Rigidbody-based, which might work, but would require me to code a lot of the other interactions that are already working out of the box with Rigidbody physics.
Use RayCasting to detect when these special collisions might occur next and handle them before the actual collision. This is where I'm leaning currently.
Anyone have a recommended best practice for this kind of thing?
Thanks in advance!
The easiest way might just be to take full control. On the correctly timed press, disable the RigidBody and the Collider. Then just move it yourself to the target location. It's really hard to get precise control over a RigidBody -- every FixedUpdate(), it might be picking up force from collisions, and there can be many FixedUpdate() calls between Update() calls.
You could write a pretty simple coroutine using a Lerp() or Slerp() between the object's current and target position. That way, you could fully control how the object moves toward its target.
Just to follow up... I attempted to "take full control" as suggested in Alex M's answer above, but that ended up making a number of other things complicated in my specific situation. However, his comments about disabling the collider in the original question led me down a different path that ended up working well...
I ended up disabling the collider for the deflecting rigidbody upon impact and setting the velocity of the deflected body directly. That way, I was able to avoiding any additional force(s) applied from Unity while the collision was active. Once the deflected object was on it's way, I just had to reenable the collider.
Thanks, Alex!

Allow NavMeshAgents to walk through each other

I'm looking for a way of setting up my humanoid NavMeshAgents to walk through each other.
I don't want them to collide with one another as there will be several players in the map and they'll need to just be able to ignore one another.
They should still be able to avoid the baked NavMesh obstacles but just ignore each other.
So I just ran into this exact problem. Googling found older or very complicated solutions. I finally found an option under NavMeshAgent --> Obstacle Avoidance --> Radius. The trick in my situation was to set the radius to something very, very tiny; relative to the actual size of the GameObject. Then the objects can pass right by (thru) each other.
You should take a look at Unity's Layer-based collision detection. You'll need to set your non-colliding humans' layers to the same layer and then uncheck the box where it meets.

In Unity, how to prevent animations from messing with the movement?

The problem:
I have a character model with a Nav Mesh Agent component. It moves perfectly well to any destination I tell it to move (using the NavMeshAgent.destination property).
But this suddenly fails as soon as I use an animation controller I downloaded from the store. The character won't run to it's destination; instead, it will endlessly run around it in circles.
I'm not sure why this happens, but I suppose the running animation somehow cripples the character's ability to turn. The Inspector, in the import setting of the relevant .fbx file shows: Average Angular Y Speed: 0.0 deg/s.
What I really, really fail to understand is why this keeps happening even though I have explicitely set NavMeshAgent.updatePosition and NavMeshAgent.updateRotation properties to true. The way I understand the documentation, this should make the character move as the Nav Mesh Agent wants it to move, and not as anything else (animations included) wants it to move?
How should I fix this problem? How should I force the animation not to meddle in the movement?
Do all your animation in place and use code to do the movement and you can uncheck root motion and use state machine values to get a better movement or use root motion and let mecanim`s retarget engine do the blending so go see for yourself what gets you better result , so I guess your problem is that your animation are not in place.
First: one of the biggest plus of Unity is its mecanim. Disabling root motion is negating a big advantage.
Second: the reason your character is running around probably is because the animator and the navmesh agent are issuing conflicting orders. Use updatePosition to false and updateRotation to true. Hence, the animator controls how fast you move and the navmesh agent controls the angular speed. Other posible cause is that your destination is unreachable. Check the Y component of the vectors and insure they are coplanar.

Can I move dynamic physics bodies using SKAction when only contact detection is needed?

I am looking at tutorial where things are defined like this:
planes are sprites with dynamic physics bodies
plane moving is done with actions by following the path
there is contact detection between bullet and plane
bullet is sprite and it has physics body set to be static (which is little unusual in my opinion)
Here is the link to tutorial for more information.
Questions:
When we use actions to move physicsBodies is there a difference how we set body's dynamic property? Because bullet is static but still there is no problem for movement.
When we have situation like this, where we don't need collision detection, but just contact detection, and we can't move sprites (enemies) by applying forces or impulses, what is a good approach? Is this approach correct?
I think this is nice way, but I would like to be fully aware what is really happening when we use this method and are there any drawbacks or possible problems.
There are posts on SO that suggest we shouldn't use actions for moving dynamic physics bodies. I am aware that we can't use this approach in every case. For example this would not work for moving platform with other object on it, because there would be no correct physics simulation between body on the platform and platform moved by action. But in cases like from this tutorial, where we only need contact detection for object that can be moved only by actions (moved along path) I suppose it's not a problem ?
static means that the body isnt affected by physics. That doesnt mean it cant be manually repositioned or moved. So if something is set to static, it participates in the physics simulation, but it isnt affected by it. Think of a plane hitting a mountain. The plane is dynamic, the mountain is just going to sit there even though its participating in the physics. But you could still move that mountain around manually using a position or an action.
Not totally understanding your question, but I'll give it a shot.
You can move physicsBody's manually (using position property or actions), but you need to ask yourself why you're doing that. You typically don't want to do it because they're bypassing the physics simulation. If you're forcing it to move around, what's the point of using a physics body in the first place.. right?
But if your physicsbody is something like a powerup that is totally static, and you just want it to move around in a circle using an action then thats fine. You probably just want to use contact detection for the bullet, powerup, etc without actually moving it around using physics. Nothing wrong with that.

Unity3D: Recalculating collisions after Physics2D.IgnoreLayerCollision()?

I have my "player" gameObject standing atop a platform. He press a combination of keys, I verify that he's standing on the right kind of platform, and I run this code:
Physics2D.IgnoreLayerCollision(playerLayer, plataformLayer);
The intention being that he'd drop down from the platform. Instead, nothing happen immediately. The player is still atop the platform and can move around - only if he gets out of it and tries to get back to it, only at that point will he fall down from it.
So I made a temporary ugly workaround:
Physics2D.IgnoreLayerCollision(playerLayer, plataformLayer);
rigidbody2D.AddForce(transform.up * jump / 1.5f);
This will force the player to jump, making Unity "recalculate" the collisions and the player will, as I want to, pass through the platform. The even weirder part is: if the jump isn't high enough (100 force at 1 mass with 0.5 gravity scale seems to be the minimum), the player will still land on the platform, even though Unity is supposed to be ignoring those collisions.
I also tried pushing the player downwards, both with force and direct velocity, but no luck - he still collides with the platform, he only stops colliding with it after being away from it once.
Also, my player Rigidbody2D Detection Mode is set to Continuous, and I tried setting the platform up in many different ways, with and without a Rigidbody2D.
Any ideas on how to make the player instantly fall down from the platform as soon as collisions start being ignored? Thanks in advance.
I had been having the exact same issue. I have an alternative solution that you may find to your liking.
Rather than disabling or moving the terrain to be ignored, temporarily set the rigidbody2D of your player gameObject to kinematic. This will not cause you to 'drop' through the platform as you would like - but it will allow you to create the illusion that you are, by briefly using transform.Translate (or Vector3.Lerp, if you like) to move your character down via code.
This will disable Rigidbody2D.AddForce, but will still allow for set movement via rigibdody2D.velocity, if that is preferable to manipulating the transform directly.
Ensure the downward velocity lasts only as long as you are Kinematic, and try to let it match the gravity of your game, and it looks pretty seamless.
If you turn the rigidbody back on too quickly, it can (even with ignoreLayers :/ ) still jump back up to the platform - but if you leave it on too long, you can drop through more than one intended one-way platform, or even :O through the bottom of the stage!
This is easily avoided if you can be careful - personally I used both MonoBehaviour.Invoke to set a very short time limit on how long the player would remain Kinematic (about 0.5 seconds), AND I disabled Kinematic as soon as they moved 0.5 units from the point where the 'hopDown' was initiated.
If your gravity / platforms / character scale are vastly different than my own, you may have to experiment with some different numbers.
This has been my first attempt at an answer on stackoverflow, so I hope it has been helpful!
One easy way to do this is after calling
Physics2D.IgnoreLayerCollision(playerLayer, plataformLayer);
You reset the player's layer:
player.gameObject.layer = playerLayer;
It's sounds like you have covered a ton of possible solutions to this problem before coming here so, good job there. I listed a few alternative ideas below. I hope they help. Good luck!
Remove the collision object from the platform itself.
Offset the collision object to be in some remote location so it will not interact with the player. Offsetting the object may cause the collision to have a similar reaction to the jump you mentioned.