Detect OnTriggerExit when disabling gameobject - unity3d

I am facing a very simple problem about Triggers, but I don't see any way to solve it. I just want the OnTriggerExit function to be called when an object inside the trigger gets disabled.
Here is the way to reproduce the problem in an empty scene :
Create a cube at (0,0,0) with a collider as trigger and the very simple following script :
public class OnTriggerExitTest : MonoBehaviour
{
private void OnTriggerExit( Collider other )
{
Debug.Log( "Exiting : " + other.name );
}
private void OnTriggerEnter( Collider other )
{
Debug.Log( "Entering : " + other.name );
}
}
Create a sphere at (0,0,0) with a Sphere collider and a Rigidbody which does not use Gravity
Move the sphere out of the box, OnTriggerExit gets called
Move the sphere back to (0,0,0), OnTriggerEnter gets called
Disable the sphere, OnTriggerExit is not called
Enable back the sphere, OnTriggerEnter is called
Obviously, I want OnTriggerExit to get called when I disable my sphere. Do you know any solution ?
I am using Unity 5.4.1f
I could use events in the OnDisable function of my sphere of course, but it's not very clean. I simply do not understand why OnTriggerExit is not called but OnTriggerEnter is.

There technically is no reason why Unity could not call OnTriggerExit in your scenario. A likely reason would be however that the "other" Collider is null given that is has been destroyed and would muck up a lot of situations if not handled.
However, you could work around it by using OnTriggerStay instead. It should be called every frame, and the first time it isn't called in your scenario that could mean the other collider got disabled.

Related

Ignore on mouse down for certain colliders in unity

I am trying to make a game object click-able to select it, the game object in question is a building in a top down game,
Here is what is looks like:
Notice how it has a 2d box collider on parent i.e. pfLumberMill and a polygon collider on the child Visual object, The function of the child's collider is for obstacle detection in a grid, here is what I mean :
Now I have a OnMouseDown on building.cs which is attached to the parent pfLumberMill, the purpose of the OnMouseDown is to select that building, i.e. :
private void OnMouseDown() {
// select building
// only triggered where the outer box collider doesn't intersect with the inner polygon collider :(
}
But what is happening is I can select the building only when I click the outer box collider that doesn't collide with the inner polygon collider, I think what happening is the inner collider hit takes precedence over the outer collider hit,
Was thinking of finding the world space on map click and figuring out the selectable area like that, but is there a easier way to this?
2: https://i.stth ack.imgur.com/pOEwk.png
I would put the collider you cant hit in front of the collider you can hit. Then I would use a script to see if you clicked the behind one.
To see how to check if they clicked on anything, see this link
I would only reccomend doing one thing differently.
Assign a variable for your camera, then assign it in start. Then use that variable to screenpointtoray.
Camera cam;
void Start()
{
cam = Camera.main;
}
void Update()
{
......
//Don't do this: Camera.main.ScreenPointToRay(...
//Do this: cam.ScreenPointToRay(...
......
}

Unity how to find if object intersects with mesh collider (not bounding box, the actual mesh)?

i know how to detect basic bounding box collisions
Collider collider1= obj1.GetComponent<Collider>();
Collider collider2= obj2.GetComponent<Collider>();
if (collider1.bounds.Intersects(collider2.bounds))
Debug.Log("collides with=" + objCollider.name);
but that's not very accurate, i'd like to get if their actual meshes collide so i tried
MeshCollider collider1= obj1.GetComponent<MeshCollider>();
MeshCollider collider2= obj2.GetComponent<MeshCollider>();
if (collider1.bounds.Intersects(collider2.bounds))
Debug.Log("collides with=" + objCollider.name);
and no difference, any suggestions please?
thanks
UPDATE, please note i forgot to add that i need this to work when timescale is zero and collisions don't work then
That's not the correct way to detect collisions. Use MonoBehaviour.OnCollisionEnter or MonoBehaviour.OnTriggerEnter instead.
OnTriggerEnter is called when the Collider other enters the trigger.
OnCollisionEnter is called when this collider/rigidbody has begun touching another rigidbody/collider.
Just attach the following script to the GameObject that will collide with another GameObject. The method will be called when the collision happens.
using UnityEngine;
public class ExampleClass : MonoBehaviour
{
void OnCollisionEnter(Collision collision) // or void OnTriggerEnter(Collider other)
{
//...
}
}

Raycasting an instantly moved collider

I need to move some transforms with attached colliders to a specific position, then check if one of them is hit by raycast.
I've done that the naive way (pseudo code) :
foreach(object in objects){
actual_position = object.transform.position
object.transform.position = object.new_position
}
if(Physics.Raycast(...)) objectHit();
// Then I revert each of them them back to their actual_position
After testing multiple times with the same context (same positions between tests for each objects), the raycast sometimes miss, sometimes not (~50/50).
Done a bit of research and found that in the Raycast doc page :
If you move colliders from scripting or by animation, there needs to
be at least one FixedUpdate executed so that the physics library can
update its data structures, before a Raycast will hit the collider at
it's new position.
So I calmed my anger and started looking for a solution.
This thread has a way using a coroutine to wait the next tick :
Raycast doesn't work properly
I'm affraid it won't work for me, as I need the objects to get back to their real position instantly.
This process can happen multiple times per frame (each time a player fire his weapon)
Is there a way to force the colliders update ?
If not... should I make my own raycasts and colliders ? :(
Thanks
Another workaround is to deactivate and activate Gameobject (attached collider) immediately. In this case collider position will be updated in single frame.
Another solution is
Physics.autoSyncTransforms and Physics.SyncTransform
Maybe you can try this out (adding to your pseudo-code):
foreach(object in objects)
{
actual_position = object.transform.position;
object.transform.position = object.new_position;
StartCoroutine(CheckToRevertOnNextFixedUpdate(object, actual_position));
}
IEnumerator CheckToRevertOnNextFixedUpdate(object, actual_position)
{
yield return new WaitForFixedUpdate();
if(Physics.Raycast(...)) objectHit();
// Then I revert each of them them back to their actual_position
}
Essentially this delays your check to the next FixedUpdate() for each object - and reverts each of them if needed. I hope this is not overcomplicated, since you only add a few lines of code.
I'm also assuming that moving the object's position for 1 FixedUpdate() frame would not have a visual effect of the the object teleporting to the new position and back. However, you can always move the collider only, and then move the rest of the transform there after the FixedUpdate().
Performance-wise, the best method seems to be updating the RigidBody.position:
private Rigidbody Rigidbody;
void Start()
{
Rigidbody = gameObject.GetComponent<Rigidbody>();
}
void Upate()
{
//.... your code
Rigidbody.position = newPosition;
}
Much faster then deactivate/activate or Physics.SyncTransform().

Unity collision not being detected

I am learning to create a simple fps game in unity the problem is that the collision does not update itself for example initially when my player is on the ground console prints "floor" by "Debug.log(collision.gameObject)" but when it intersects other objects such as a cube console will print out "cube" but when I walk away from it , console does not change back to "floor" Why????
I am using transform.translate to move and jump and using method OnCollisionEnter for collision detection
OnCollisionEnter is triggered only when object enters the collider.
A) Make a list of all encountered objects by adding them when OnCollisionEnter happens and removing when OnCollisionExit happens. Then whenever you need to make sure you are on "floor" check it in the list.
B) Use OnCollisionStay and every frame you will be notified if you are touching the "floor".
Remember one thing, the other object you want to collide with need to have a collider component asigned, make sure of it. Join this with the previous answer.
I recommend to verify collision.
Here on simple example:
void OnCollisionEnter (Collision col){
if (col.gameObject){
Debug.Log("Object name : "+ col.gameObject.name);
}
}

Why does not my particle system collision work?

I have added a particle system where I have checked the collider option and added a world particle collider. See the image below.
In the script that is attached to the particle system I have:
void OnParticleCollision(GameObject other) {
Debug.Log("Particle was hit!");
}
The bullets that are fired donĀ“t seem to hit the particles since the above message is not printed. The bullets are spheres with a sphere collider and a rigidbody attached. The rigidbody is set to non-kinematic (the checkbox is not checked) if that matters.
Also, the bullet object has a script attached with the same lines as above:
void OnParticleCollision(GameObject other) {
Debug.Log("Bullet was hit!");
}
But it is not printed as well.
What am I missing?
Double check that you have this script attached to your particle system and not any arbitrary gameobject.
Check if you have "Is trigger" disabled on Sphere Collider, or you're particles too small and don't hit the actual collider.
Tried to simulate your situation, all works fine.