I cast Raycast to only one existing Box collider in scene
if (Physics.Raycast(mousePositionInWorld, transform.forward, 10))
{
Debug.Log("Ray hit something");
}
I get message Ray hit something
But i never get trigger on the box collider
void OnTriggerEnter(Collider other) {
Debug.Log("Menu hit");
}
Target object is gameObject only with Box collider, and script for trigger checking
OnTriggerEnter (and other collider event methods) are only called if a collision actually takes place but not by casting a ray. To solve your problem it depends on the your use case.
If you want to react just before the real collision, you can enlarge your collider to be for example 1.5 in size of the mesh
If you need both cases i.e. react on direct collisions and in some other situations need to take some actions before, you should split your code, e.g.:
if (Physics.Raycast(mousePositionInWorld, transform.forward, 10)) {
doSomething ();
}
void OnTriggerEnter(Collider other) {
doSomething ();
}
void doSomething () {
}
Related
Trying to figure out how to destroy an object by clicking on it. I have tried using
public void Destroy()
{
if (Input.GetMouseButton(0))
Destroy(GameObject);
}
but realise that this will destroy all gameobjects the script is attached to instead of the one I am clicking on.
Try this one:
public void OnMouseDown() => Destroy(gameObject);
Definitely the best way is to implement IPointerClick interface,
using UnityEngine;
using UnityEngine.EventSystems;
public class ClickDestroy : MonoBehaviour, IPointerClickHandler
{
public void OnPointerClick(PointerEventData eventData)
{
GameObject.Destroy(gameObject);
}
}
This will work both for UI and for 3D Objects, as long as your camera has PhysicsRaycaster and an EventSystem exists on scene
You can get the mouse position on the screen and fire a raycast from that location. If it hits a gameobject then you can pass it to a function to delete it.
void Update {
//Check for mouse click
if (Input.GetMouseButton(0))
{
//Create a ray from mouse location
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit = new RaycastHit();
//Check if the ray hit a gameobject, gameobject will likely need a collider
//for this to work
if (Physics.Raycast(ray, out hit))
{
//If the ray hit a gameobject, destroy the gameobject
Destroy(hit.gameobject)
}
}
}
When destroying gameobjects, make sure your specifying the gameobject component and not the script or another component of the gameobject.
This code can be improved by defining a camera object in your code and assigning a camera to it in the inspector instead of it defaulting to the main or setting up full player controls in unity (Which I can't remember how to do off the top of my head I'm afraid)
I checked nearly every answer for this, but those were mostly simple errors and mistakes.
My problem is that OnCollisionEnter is not called even when colliding whith other rigidbody.
here is the part what does not get called:
void OnCollisionEnter(UnityEngine.Collision col) {
Debug.Log("collision!!!");
foreach(ContactPoint contact in col.contacts) {
//checking the individual collisions
if(contact.Equals(this.target))
{
if(!attacking) {
Debug.Log("hitting target");
} else {
Debug.Log("dying");
//engage death sequence
}
}
}
}
Not even the "collision!!!" message appears. Do I understand the usage wrong, or did I forget something?
Are you using 2D colliders and rigidbodies? If so use this function instead of OnCollisionEnter
void OnCollisionEnter2D(Collision2D coll)
{
Debug.Log(coll.gameObject.tag);
}
You need to make sure that the collision matrix (Edit->Project Settings->Physics) does not exclude collisions between the layers that your objects belong to.
Unity Docs
You also need to make sure that the other object has : collider, rigidbody and that the object itself or either of these components are not disabled.
Try this
http://docs.unity3d.com/Documentation/ScriptReference/Collider.OnCollisionEnter.html
using UnityEngine;
using System.Collections;
public class Example : MonoBehaviour {
void OnCollisionEnter(Collision collision) {
foreach (ContactPoint contact in collision.contacts) {
Debug.DrawRay(contact.point, contact.normal, Color.white);
}
if (collision.relativeVelocity.magnitude > 2){
audio.Play();
}
}
}
Here is what I do:
Make sure that object you wish to collide with target has non-kinematic rigidbody and mesh collider. My hitter object is a cube and just change its collider to mesh collider
On mesh colider inspector make sure you enable convex. Please see more mesh collider inspector detail here
Now your OnCollisionEnter works. I hope this helps you.
because you misstyped class name of parameter. this makes no error also not works.
eg:
OnCollisionEnter(Collider other) //this is wrong
OnCollisionEnter(Collision other) //this is correct
You just need attach script to the same object, whose need detects the collision.
I'm trying to make a player controller that jumps only when a specified in a property Collider collides with anything. For now, I can detect when a collision has occurred, but can't detect which are the two bodies that have collided. Does the event trigger only when one of the colliding bodies is the one that the script is applied to. If so, how can I handle events on behalf of other objects (or even better, detect global collisions)
Here is my player controller hierarchy:
Capsule
|
+- Camera
|
+- Floor Collider
P. s.: Sorry for the question's short length
Let me see if i got your question, you want to detect when the player is touching the floor so that it can only jump when on the floor. Is this right?
The floor has a Collider as well right? Add a tag on the floor object so that we can identify who is the Collider.
And then on the Player Controller do something like:
void OnCollisionEnter(Collision other)
{
if(other.gameObject.tag == "floor")
{
allowJump = true;
}
}
And the opposite so that we know that the player can't jump
void OnCollisionExit(Collision other)
{
if(other.gameObject.tag == "floor")
{
allowJump = false;
}
}
So, I'm making a coin system. When a player collides with trigger collider, i want it to disable only the object it collided with.
this.SetActive(false);
Finding object by name
void OnTriggerEnter (Collider other)
{
if (other.tag == "Coin")
{
this.SetActive(false);
}
}
/
You were very close with your original solution, but you may be misunderstanding what is actually happening here. So I've documented my solution to show the difference.
/* The following script is called when a Rigidbody detects a collider that is
* is set to be a trigger. It then passes that collider as a parameter, to this
* function.
*/
void OnTriggerEnter (Collider other)
{
// So here we have the other / coin collider
// If the gameObject that the collider belongs to has a tag of coin
if (other.gameObject.CompareTag("Coin"))
{
// Set the gameObject that the collider belongs to as SetActive(false)
other.gameObject.SetActive(false);
}
}
If you want the coin to be removed from the scene, because you don't expect it to ever be reactivated, then you can amend this code to the following:
void OnTriggerEnter (Collider other)
{
if (other.gameObject.CompareTag("Coin"))
{
// Removes the coin from your scene instead
Destroy(other.gameObject);
}
}
Is there a way to detect if the collider on the player (with a rigidbody) object is not colliding with any other collider in a 2D environment?
Not per se, but there are two ways you can get the information. It's easiest to keep an int counter, and increment it in OnCollisionEnter and decrement in OnCollisionExit. When the counter is 0, there are no collisions.
Another way, which will tell you which colliders are overlapping but not necessarily if they are touching, is to use a physics function. Note which type of collider you have--sphere, capsule, box. Knowing the size/shape/position of the collider, you can call Physics.OverlapBox, Physics.OverlapCapsule, or Physics.OverlapSphere. Give the function the same shape as your collider, and it will return the colliders that overlap that space. (For 2D colliders, you can use the Physics2D.Overlap* functions.)
/edit - actually piojo's idea with counters is better, just use int instead of bool.
One way would be to add an int to your script called collisions and set it to 0. Then if at any point the collider fires OnCollisionEnter just increment it, and in OnCollisionExit decrement it.
Something like this should work for 3D:
public int collisions = 0;
void OnCollisionEnter(Collision collision)
{
collisions++;
}
void OnCollisionExit(Collision collision)
{
collisions--;
}
https://docs.unity3d.com/ScriptReference/Collider.OnCollisionEnter.html
https://docs.unity3d.com/ScriptReference/Collider.OnCollisionExit.html
I don't understand what's with all the number keeping. I just did this for when my character jumps or falls off the edge and it works great.
Both my player and terrain have colliders. I tagged my terrain with a "Ground" tag.
Then check if I am currently in contact with the collider with OnCollisionStay()
void OnCollisionStay(Collision collision)
{
if (collision.collider.tag == "Ground")
{
if(animator.GetBool("falling") == true)
{
//If I am colliding with the Ground, and if falling is set to true
//set falling to false.
//In my Animator, I have a transition back to walking when falling = false.
animator.SetBool("falling", false);
falling = false;
}
}
}
void OnCollisionExit(Collision collision)
{
if (collision.collider.tag == "Ground")
{
//If I exit the Ground Collider, set falling to True.
//In my animator, I have a transition that changes the animation
//to Falling if falling is true.
animator.SetBool("falling", true);
falling = true;
}
}
void OnCollisionEnter(Collision collision)
{
if (collision.collider.tag == "Obstacle")
{
//If I collide with a wall, I want to fall backwards.
//In my animator controller, if ranIntoWall = true it plays a fall-
//backwards animation and has an exit time.
animator.SetBool("ranIntoWall", true);
falling = true;
//All player movement is inside of an if(!falling){} block
}
}