OnCollisionExit is not being called - c#

Why is OnCollisionExit not being called? I am using both OnCollisionEnter and OnCollisionExit but unfortunately only OnCollisionEnter is being called.
public bool HandleCollided = false;
public void OnCollisionEnter(Collision col)
{
if(col.gameObject.name == "RightHandAnchor")
{
HandleCollided = true;
}
}
public void OnCollisionExit(Collision col)
{
if(col.gameObject.name == "RightHandAnchor")
{
HandleCollided = false;
}
}

It's impossible to tell why your code isn't working based the given snippet - this code depends on the configuration of each of the GameObjects' inspector windows in the editor.
Both the GameObject that this script is attached to and the colliding GameObject must have one Collider component attached to each of them (for example, a BoxCollider component or a SphereCollider component). Both Colliders must have their isTrigger checkboxes disabled. The GameObject that this script is attached to must also have a Rigidbody component attached.
In order to debug this situation, add Debug.Log() statements in your functions. This is generally good practice, and it might be that the function is being called but the conditional statement is not true.
Here are some additional ideas on what might be going wrong:
You may be changing the name of the colliding GameObject somewhere else in your code.
You may be destroying the GameObject.
It might be that neither function was being called and HandleCollided was being changed elsewhere in your code.
It might be that the parameter, col, is not what you expect.
public void OnCollisionEnter(Collision col)
{
Debug.Log("Collision Enter!");
Debug.Log(col.gameObject.name);
}
public void OnCollisionExit(Collision col)
{
Debug.Log("Collision Exit!");
Debug.Log(col.gameObject.name);
}

You need a non-kinematic rigidbody attached to your object to get the event for OnCollisionExit

So you said "There are two objects that collides with each other. One has sphere collider attached to it and another has box collider. One of the objects have rigidbody attached as well." On which one is the code? and yes this matters! only 1 of the objects will keep track of the exit meaning that if it's the non-kinematic it will not work.

Unfortunately using OnCollisionExit did not work so instead I used OnTriggerEnter and OnTriggerExit. I activated "isTrigger" for both objects.
public void OnTriggerEnter(Collider col)
{
Debug.Log("entered");
if (col.gameObject.name == "RightHandAnchor")
{
HandleCollided = true;
}
}
public void OnTriggerExit(Collider other)
{
Debug.Log("exit");
if (other.gameObject.name == "RightHandAnchor")
{
print("No longer in contact with " + other.transform.name);
HandleCollided = false;
}
}

Related

How to make a program to make an object appear and disappear by entering and exiting a trigger?

I need a code to make an object appear when I enter a trigger object and disappear when exit the trigger object.
GameObject GhostApparition;
// Use this for initialization
void OnTriggerEnter (Collider other)
{
if (other.CompareTag("Player")) ;
{
//????
}
}
I want the object to appear when I enter a trigger object and disappear when I exit the object. Also the actual mesh should disappear too.
You can manipulate the state of a gameObject with
gameObject.SetActive(true);
gameObject.SetActive(false);
You just have to call it in your TriggerEnter and TriggerExit. I don't know if you want to make your "ghostapparition" inactive, but then it is:
GhostApparition.SetActive(true);
GhostApparition.SetActive(false);
To solve this problem, simply do it:
GameObject GhostApparition;
// Use this for initialization
void OnTriggerEnter (Collider other)
{
if (other.tag == "Player") ;
{
GhostApparition.SetActive(true);
}
}
void OnTriggerExit (Collider other)
{
if (other.tag == "Player") ;
{
GhostApparition.SetActive(false);
}
}
But be aware when you doing it with GameObjects which contains behaviors. If you deactivate it, then activating again, it'll run void Start again and reset your variables. Sometimes you not gonna want it.
So I suggest, in these times, to you just deactivate the GameObject MeshRenderer Component.
You could activate/deactivate the game object, like this:
gameObjext.SetActive(true); //or false
By activate/deactivate all attached components will be enabled/disabled as well, doc.
….monobehavior:
public GameObject object;
void Start()
{
object.SetActive(false);
object2.SetActive(false);
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Player")
{
{
object.SetActive(true);
object2.SetActive(false);
}
}
}
/// void OnTriggerStay and 'object2' are extras (for if u want a keycode to show an additional text)
void OnTriggerStay(Collider other)
{
if (object.activeInHierarchy && Input.GetKeyUp(KeyCode.E))
{
object.SetActive(false);
object2.SetActive(true);
}
}
void OnTriggerExit(Collider other)
{
object.SetActive(false);
object2.SetActive(false);
}
...

Unity 2D: Collision trigger

So here it is, Iam making a game for my thesis. The game is called hacky sack, Iam having a problem when my trigger is true because the collision for my character and the object is passing through and if idon`t have a trigger it was just basically hitting it even when my Player is running.
And can you guys help me on how the Object/Sack going up randomly when it hit. So here is my code :
public void Sipa()
{
if (canSipa == true)
{
_pitcha.GetComponent<Rigidbody2D>().AddForce(new Vector2(-400, 1000));
}
}
}
And here is for my object
private void OnTriggerEnter2D(Collider2D collision)
{
if(collision.gameObject.tag == "Player")
{
_player.GetComponent<PlayerManager>().canSipa = true;
}
}
private void OnTriggerExit2D(Collider2D collision)
{
if (collision.gameObject.tag == "Player")
{
_player.GetComponent<PlayerManager>().canSipa = false ;
}
}
}
add a second collider, slightly larger then the first, mark it trigger. leave the smaller inner collider for physics. you "foot" should enter the trigger and activiate it, then collide with the inner collider. make sure the collider marked trigger is the larger one.

Unity 2D Platforms Show on Collision

How can I make a group of platforms appear when colliding with it's trigger?
I would like to walk into the trigger, which will turn on the 'StarPlatforms' in the inspector, revealing every thing that is a child of it. I have only got it to do the exact opposite:
Before collision
After Collision
Children of StarPlatfroms
The script on the StarPlatforms:
public class AppearTrigger : MonoBehaviour {
private GameObject StarPlatforms;
void Start() {
StarPlatforms = GameObject.Find("StarPlatforms");
StarPlatforms.gameObject.SetActive (true);
}
void OnTriggerStay2D (Collider2D col) {
if (col.gameObject.tag == "Player") {
StarPlatforms.gameObject.SetActive (false);
}
}
}
I have tried swapping the .SetActives too false then true and it unchecks in the inspector on Play but stays hidden on collision with the trigger.
Thank you for your time.
ps: this is my first go at Unity & C#
SetActive just sets whether it is part of the main game loop or not. To make a platform invisible or visible use it's Renderer component and deactivate that instead.
gameObject.GetComponent<SpriteRenderer>().enabled = false;
I would like to walk into the trigger, which will turn on the
'StarPlatforms' in the inspector. I have tried swapping the .SetActives too false then true
You seem to be guessing which one works. This is how SetActive work:
To turn on or activate an object, pass true to SetActive. To turn it off or deactivate it, pass false to it. Also, this should be done in the OnTriggerEnter2D function not OnTriggerStay2D.
The OnTriggerStay2D function is called when collision each frame collision is still touching. The OnTriggerEnter2D function is called when there is a collision. OnTriggerExit2D is called when there is no longer a collision.
void OnTriggerEnter2D (Collider2D col)
{
if (col.CompareTag("Player"))
{
StarPlatforms.gameObject.SetActive (true);
}
}
If you also want to turn it of or de-activate it when they no longer touch, pass false to the SetActive function in the OnTriggerExit function.
void OnTriggerExit2D(Collider2D col)
{
if (col.CompareTag("Player"))
{
StarPlatforms.gameObject.SetActive (false);
}
}
Not related to your issue but it's a good practice to use CompareTag instead of gameObject.tag.
This is what worked:
public class AppearTrigger : MonoBehaviour {
GameObject[] StarPlatfromArray;
void Start() {
StarPlatfromArray = GameObject.FindGameObjectsWithTag("Cave");
for (int i = 0; i < StarPlatfromArray.Length; i=i+1) {
StarPlatfromArray [i].gameObject.GetComponent<BoxCollider2D> ().enabled = false;
StarPlatfromArray [i].gameObject.GetComponent<SpriteRenderer> ().enabled = false;
}
}
void OnTriggerEnter2D (Collider2D col) {
StarPlatfromArray = GameObject.FindGameObjectsWithTag("Cave");
for (int i = 0; i < StarPlatfromArray.Length; i++) {
StarPlatfromArray [i].gameObject.GetComponent<BoxCollider2D> ().enabled = true;
StarPlatfromArray [i].gameObject.GetComponent<SpriteRenderer> ().enabled = true;
}
}
}

Unity - GameObject won't destroyed when hit a prefab

In the game you controll a ball (Sphere) and two types of boxes falling down: deathCube and goldCube. When the Sphere hit the DeathCube, then the Sphere is destroyt, but it not get destroyed and I don't know why. The cubes are prefabs and they have a tag(DeathCube, GoldCube).
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "DeathCube")
{
Destroy (gameObject);
}
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "GoldCube")
{
gold++;
}
}
If the Sphere hit the goldCube you get points, but this doesn't work too.
If you don't have a rigidbody attached to at least one of the objects in the collision (ball or cube), then the trigger event won't be initiated.
From the documentation:
Notes: Trigger events are only sent if one of the colliders also has a rigidbody attached
Source: https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnTriggerEnter.html
Try merging the two OnTriggerEnter's into one.
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "DeathCube")
{
Destroy (gameObject);
}
if (other.gameObject.tag == "GoldCube")
{
gold++;
}
}
I believe that the second one is overriding the first, never allowing the Destroy() to be called. I would've assumed the compiler would throw an error with this, but you don't seem to have indicated that.

unity OnTriggerStay2D() for two triggers

I am using unity 5 c# and I have a gameobject with 2 trigger colliders one of them is in a different location.
I need to be able to use OnTriggerStay2D and OnTriggerEnter2D for them but I need to find what trigger is being entered. Right now if I enter the 1st(polygon) trigger the OnTriggerEnter activates for the 2nd(box).
How can I Tell the two colliders apart???
public void OnTriggerEnter2D(Collider2D other) //2nd collider trigger
{
if (other.tag == "Player") {
Found = true; //if the player is in shooting range
Idle = false;
}
}
public void OnTriggerStay2D(Collider2D other) //1st collider trigger
{
if (Found != true) {
if (other.tag == "Player") {
Shield = true;
Idle = false;
}
}
}
public void OnTriggerExit2D(Collider2D other) //2nd collider trigger
{
if (other.tag == "Player") {
Found = false;
Shield = false;
Shooting = false;
Idle = true;
}
}
I have tried making the 1st trigger public void OnTriggerStay2D(PolygonCollider2D other) but it says "This message parameter has to be of type: Collider2D
The message will be ignored."
What I am trying to do is have a polygon trigger in front of the gameobject and a different box trigger closer to the gameobject so when you go near the gameobject you enter the 1st trigger and it puts its shield up but when you get close to it (within shooting range of it) it will put its shield down and start shooting you.
Well collider2d detects all types of 2d colliders. It doesn't matter if it's polygon or just a box. As the documentation suggestions it doesn't need to be public or private. It only takes a collider2d as it's argument however.
For debugging purposes why not use print?
Print("you've entered the trigger function");
Also I wouldn't use 2 different trigger colliders on the same GameObject. Why not just make 2 separate gameobjects so you can have more thorough detection. Each GameObject with its own trigger collider can have different tags.
If you have to use 2 trigger colliders on one object. Which isn't the best idea. You could use shapeCount to determine which one it's hitting. Although like I said I would warrant against doing 2 trigger colliders on the same object when whatever you're trying to do can be easier on two separate objects.
However links aren't usually prohibited I think. I would watch and study these videos. They're very useful for explaining the engine and they really aren't even that long.
https://unity3d.com/learn/tutorials/modules/beginner/2d
They even have a video explaining 2d colliders.
This is my fix. In one of my games I have a boulder, I have a trigger which will delete a block below it so it falls, I then have another trigger which tells the boulder to start moving left or right I then also have another trigger which will delete the boulder once the boulder comes in contact.
So what you can do is create 2 new game objects, create a new CS file and name them appropriately, then with those two new classes allow them to take in the gameobject you are referring to in your question.
Then when they are triggered you can use code from their class.
So your first class would become something like this
public void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Player") {
Enemy.Found = true; //if the player is in shooting range
Enemy.Idle = false;
}
}
public void OnTriggerExit2D(Collider2D other)
{
if (other.tag == "Player") {
Enemy.Exit2DTrigger();
}
}
Then the other class would be something like this
public void OnTriggerStay2D(Collider2D other)
{
if (Enemy.Found != true) {
if (other.tag == "Player") {
Enemy.Shield = true;
IEnemy.dle = false;
}
}
}
public void OnTriggerExit2D(Collider2D other)
{
if (other.tag == "Player") {
Enemy.Exit2DTrigger();
}
}
Then in your Enemy class you would have
public void Exit2DTrigger()
{
Found = false;
Shield = false;
Shooting = false;
Idle = true;
}
P.S. also don't you need to use other.gameObject.tag == "Player" ?

Resources