Unity how to check what object triggered a trigger - c#

I am in the middle of creating a simple 3d platformer in unity and i'm trying to make it so if you are in a certain radius and you hit the "f" key the enemy will disappear. the way i'm checking to make sure the enemy is close enough to be attacked is to have trigger sphere and when its triggered and you press "f" the enemy will be removed. i'm currently trying to see what collided with the trigger but i cant figure it out. here is my current code
using UnityEngine;
public class PlayerCombat : MonoBehaviour
{
public GameObject Enemy1;
public GameObject Enemy2;
public GameObject Enemy3;
public GameObject Enemy4;
// Update is called once per frame
void OnTriggerEnter (Trigger triggerInfo)
{
if (triggerInfo.collider.tag == "Enemy" & Input.GetKey("f"))
{
if (triggerInfo.collider.name == Enemy)
{
Enemy1.SetActive(false);
}
}
}
}

The signature is and has always been OnTriggerEnter(Collider) otherwise that message method will not be recognized by Unity and not get called at all!
And then you already have the according Collider ... what else do you need?
public class PlayerCombat : MonoBehaviour
{
// There is no need to know the enemy references beforehand at all
// you will get all required references from the Collider parameter of OnTriggerEnter itself
// I personally would however expose these two settings to the Inspector to be more flexible
// this way you can adjust these two settings within Unity without having to touch your code
public string listenToTag = "Enemy";
public KeyCode listenToKey = KeyCode.F;
// The signature has to be this otherwise the message method is never invoked at all
private void OnTriggerEnter (Collider other)
{
// Rather use "CompareTag" instead of `==` since the latter will silently fail
// for typos and nonexistent tags while "CompareTag" shows an error which is good for your debugging
// And in general you want to use the logical "&&" instead of the bitwise operator "&" for bools
if (other.CompareTag(listenToTag) && Input.GetKey(listenToKey))
{
// simply set the object you collide with inactive
other.gameObject.SetActive(false);
}
}
}
Finally just make sure that all your enemy instances actually have the tag Enemy

First, I'm pretty sure OnTriggerEnter takes a Collider as its parameter, no? https://docs.unity3d.com/ScriptReference/Collider.OnTriggerEnter.html
You can get the name of the collided object like so
//Upon collision with another GameObject,
private void OnTriggerEnter(Collider other)
{
Debug.Log($"collided with {other.gameObject.name}");
//you can check for specific components too
MyComponent myComponent = other.GetComponent<MyComponent>();
if (myComponent != null) {
// do something if it has that component on it!
}
}

Related

C# Unity not displaying Debug.Log() console

I am writing a script that shows a collision between one object and an obstacle. The code runs but does not output within the console. Is there something that I am doing wrong?
using UnityEngine;
public class collision : MonoBehaviour{
void OnConllisionEnter (Collision collisionInfo)
{
if(collisionInfo.collider.tag == "Obstacle")
{
Debug.Log("We Hit an obstacle!");
}
}
}
I added a tag to the object as I will be adding more obstacles to simplify the process. I checked for semicolons and any other errors that would stand out to me. I am not sure what I am supposed to change or if I am missing something.
You actually have a typo in the methods name
// Here
// |
// v
void OnConllisionEnter (Collision collisionInfo)
The code should be
using UnityEngine;
public class collision : MonoBehaviour{
void OnCollisionEnter (Collision collisionInfo)
{
if(collisionInfo.collider.tag == "Obstacle")
{
Debug.Log("We Hit an obstacle!");
}
}
}
When using OnConllisionEnter, check your collider component to make sure the [Is Trigger] flag isn't checked
Collider Component, Is Trigger Flag
Also, remember that both objects have to have a collider component attached to them and only one of them will need a rigid body component attached to it (both of which have to match the correct world space, i.e. 2D/3D RigidBody and Collider.
More about Collisions:
https://docs.unity3d.com/ScriptReference/Collider.OnCollisionEnter.html

Unity 3D Counting Number of Agent Passes through a door

I am trying to make fire evacuation simulation by using Unity. I need to count the number of agent passes through the exit door during the evacuation. Is there any way to do it ?
You could set up a simple trigger collider system.
First, you would place a box collider at the exit door, and set it to trigger so it isn’t a solid object (objects can path through it, rather than walk into it). Now, add a Rigidbody to this box collider, and set first drop-down menu that says ‘Dynamic’ to ‘Kinematic’. Now, a way to count them. We will ad the following script to the box collider object:
using UnityEngine;
public class ExitDoor : MonoBehavour
{
void OnTriggerEnter(Collider obj)
{
if (obj.gameObject.tag == “agent”)
{
}
}
}
This doesn’t work yet, because we don’t have anything other than an OnTriggerEnter statement. OnTriggerEnter is called every time either a game object passes through a trigger collider or this game object passes through a trigger collider. We set up an if statement to detect if the game object that passed through it has a certain tag. We are searching for a tag called “agent”. Set each agent’s tag to “agent”. Now we should start a counting system.
using UnityEngine;
public class ExitDoor : MonoBehavour
{
public int agents;
void OnTriggerEnter(Collider obj)
{
if (obj.gameObject.tag == “agent”)
{
agents += 1;
}
}
}
Now, we add 1 to a variable each time an agent enters the collider. The only problem with this is that if the agent goes through the collider twice, it will count it twice.
This system is done, but now you might want to access this from different scripts. We will use GetComponent<>() to access the script. Add this to your game management script, or whatever you want to be accessing this:
using UnityEngine;
public class GameManagement : MonoBehavour
{
public GameObject ExitDoor;
public int agents;
void Update()
{
agents = ExitDoor.GetComponent<ExitDoor>().agents;
if (agents == 10)
{
Debug.Log(“10 agents have exited.”);
}
}
}
Now, we access the script ExitDoor, and get agents from it. Make sure you set the ExitDoor variable from the game management script to the box collider game object used for counting.
This was untested and if you get any bugs or this wasn’t what you wanted, comment on this post to ask me.

Make a GameObject indestructible

I am making a shooting game using Raycasts in Unity. I have a gameObject which is a cube (The ground for my game). That cube can be destroyed by using Destroy() method. How do I make it indestructible so that it doesn't get destroyed even after using the Destroy() method?
This my FPS gun script so far:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Gun : MonoBehaviour
{
public float damage = 20f;
public float range = 150f;
//public GameObject ground;
public Camera fpsCamera;
void Start()
{
//DontDestroyOnLoad(ground);
}
void Update()
{
if (Input.GetButtonDown("Fire1")) {
Shoot();
}
}
void Shoot()
{
RaycastHit hitObject;
if (Physics.Raycast(fpsCamera.transform.position, fpsCamera.transform.forward, out hitObject, range) && hitObject.transform.name != "Ground") {
Destroy(hitObject.transform.gameObject);
}
}
It sounds like you want to sort which objects are destroyed somehow. The most simple way is of course to not call the Destroy method on that object in the first place.
However since you explain in the comments you wish to shoot and destroy some objects but not all. I would in your case make a script which either checks the tag, layer or calls a method in a script on each object.
For example, you try something similar to this:
ObjectProperties : MonoBehaviour{
public boolean CanBeDestroyed = true;
}
Add that script to the objects you shoot at.
And then when your raycast hits an object, use GetComponent on the object shot to try get ObjectProperties from that object. If the object hit has a ObjectProperties that isn't null, and that ObjectProperties has CanBeDestroyed set to be true. Then you may destroy the object.
The most simple way of achieving this, is using tags. Create a tag by highlighting the object. In the Inspector open the tags tab. Then create a tag and assign it to your object. The last thing you need to do is to check in code which tag the object you hit has.
if (Physics.Raycast(fpsCamera.transform.position, fpsCamera.transform.forward, out hitObject, range) && hitObject.transform.name != "Ground") {
switch (hitObject.tag)
{
case "immortal": //Nothing happens
break;
case "veryweak": //Objects with this tag get destroyed
Destroy(hitObject.transform.gameObject);
break;
default: //Objects that do not have a tag and do not match any of the above get destroyed
Destroy(hitObject.transform.gameObject);
break;
}
}
Hope that helps.

A collision triggers an animation

I am trying to make my player hit an object, destroying the object and triggering an animation, but everything I try causes an error. I am relatively new at c# so the answer may be obvious but I need help. How can I set it up so that the collision will cause the object to disappear and the player to play an animation? Here is the script I am currently trying.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class succ : MonoBehaviour
{
public float speed = .15f;
public static float jumpSpeed = 170f;
void Start()
{
GetComponent<ConstantForce2D>().enabled = false;
GameObject.Find("goal");
}
public bool animation_bool;
private object coll;
private object other;
void Update()
{
OnCollisionStay2D(Collision2D coll);
{
if (coll.gameObject.tag == "succ") ;
{
animation_bool = true;
GetComponent<Animator>().SetBool("succ", animation_bool);
GetComponent<ConstantForce2D>().enabled = true;
Destroy(other.object);
}
}
}
private void Destroy(object gameObject)
{
throw new NotImplementedException();
}
private void OnCollisionStay2D(Collision2D collision2D, object coll)
{
throw new NotImplementedException();
}
}
There are a few things I can see that are wrong, but I'll start by answering your question.
I suggest you change your MonoBehaviour method OnCollisionStay2D to OnCollisionEnter2D. OnCollisionStay2D is "sent each frame where a collider on another object is touching this object's collider". OnCollisionEnter2D is "sent when an incoming collider makes contact with this object's collider".
I believe you are looking for the latter since you only want to trigger this once during the collision. You are also destroying the other object, making it impossible to call OnCollisionStay2D anymore even if you wanted to do so.
You should also remove your Update method. I honestly do not understand what you are trying to achieve there now. All of the OnCollision methods get called automatically; you do not have to call them yourself.
Then you can use the Awake and OnCollisionEnter2D methods as follows
public class Succ : MonoBehaviour
{
private Animator animator;
private void Awake()
{
// You can already get a reference to the Animator on Awake
// This way you do not have to do it on every collision
animator = GetComponent<Animator>();
}
// Use OnCollisionEnter2D instead since the code
// needs to be excecuted only once during the collision
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("succ")
{
// Assuming that you only want to trigger an animation once
// to reflect attacking or colliding, you could use SetTrigger
// instead. Otherwise you need to use SetBool again to set it
// back to false. You should then change the Animator parameter
// accordingly, from a bool to a trigger.
animator.SetTrigger("succ");
Destroy(collision.gameObject);
}
}
}
Apart from this, I have a few things I would like to comment on:
I am not sure what you are trying to achieve by setting your ConstantForce2D component to false on Start and then setting it to true on collision.
You seem to be using GameObject.Find on Start. GameObject.Find is something that should be very rarely used. It can be extremely expensive, especially if your Scene has a lot of GameObjects in it; this is because it simply goes through the Hiearchy, comparing the parameter string to names of GameObjects until it either finds a match or runs out of GameObjects.
Moreover, you are using GameObject.Find on Start to look for a GameObject, but then you do not store that anywhere, making the whole finding process completely pointless.
Overall, I recommend you to take a look at all of the different learning resources offered by Unity themselves. Your question is about fairly basic functionality that is certainly covered during all of the different tutorials.

Detect Collision for an instantly refreshed object

so i have an old code for a "Connect4" game it was written years ago, now i am having a big problem getting it results and rebuild them for a unity3D project.
the problem is that every gameObject (i've managed to instanciate in the scene) is, meant to be destroyed and reinstantiated every frame (and i have the feeling that is really more that a frame time); wanting to get the color of each gameobject in time seem to be really challenging, i am supposed now to not enter the code created i am only supposed to get the information from what i get as graphical results.
so now i have a board of boxes having a grid disposition that changes colors according to the player turns (red for the cp and yellow for the plyer).
i created a fixed boxes having colliders and wanted to get the game objects colliding with it everyframe but i failed .
PS: i tested this code and every solution i found in this community hope to find somehelp, thank you.
using UnityEngine;
using System.Collections;
public class SelectorCode : MonoBehaviour
{
public Collision other;
public GameObject GO;
void OnTriggerEnter(Collider other)
{
GO = other.gameObject;
}
void OnTriggerStay(Collider other)
{
GO = other.gameObject;
}
void OnTriggerExit(Collider other)
{
GO = other.gameObject;
}
void Update()
{
GO = this.other.gameObject;
}
}
First make sure the object to which the SelectorCode component is attached has a trigger collider (property "Is Trigger" is checked).
Next you'll get an error in the Updatemethod with GO = this.other.gameObject; since other is never assigned. I think you should remove that line.
Finally, in OnTriggerExit you put in GO the object that is leaving your collider, that doesn't make sense, you should probably assign GO to null at this point :
void OnTriggerExit(Collider other)
{
if (other.gameObject == GO)
{
GO = null;
}
}

Categories