So in my game, there's a gun that sprays bullets, and I'm trying to make a gameObject destroy on collision with the bullets. The bullets are based off of one gameObject (Capsule). I've tried these two scripts so far:
using UnityEngine;
using System.Collections;
public class whenshot : MonoBehaviour {
void OnCollisionEnter(Collision col)
{
if (col.gameObject.name == "Bullet")
{
Destroy(col.gameObject);
}
}
}
and:
using UnityEngine;
using System.Collections;
public class whenshot : MonoBehaviour {
void OnCollisionEnter(Collision col)
{
if (col.gameObject.name == "Bullet")
{
Destroy(this); //the difference between the two is that I changed "col.gameObject" to "this"
}
}
}
I'm shooting the object but it's not disappearing/destroying itself. How can I fix this?
Here's a visual if it helps:
this refers to the object instance of the caller (this is basic OOP), i.e., whenshot, and not gameObject. So the second sample is effectively Destroying the instance of the script from the gameObject it is attached to.
The first script is technically fine, and should work, provided these conditions are met:
Either the projectile (bullet) or the target (or both) have a non-kinematic rigidbody component attached. (Unity docs.)
Both have 3D Collider components.
The name of every single bullet gameObject that collides with the target is exactly "Bullet".
All projectile objects have this script as a component.
Some suggestions
Use prefabs and tags: take your bullet primitive and store it as a prefab. Add a tag to the prefab called "Bullet". Do the same for the target and tag it as "Target". Tag the player as "Player". In the "gunController", set a reference to the bullet prefab and make it Instantiate bullets on whatever trigger you're using. In the bullet's script, use CompareTag("Target") instead of == and Destroy both the target gameObject and this.gameObject.
It seems to me that the above is the behaviour you want. If that is the case, there is no delay between collision and destruction, and hence no need to simulate physics whatsoever. Unless you have some other physics interactions with bullets/targets, mark the one without a rigidbody as a Trigger.
A Strong Suggestion
Go through Unity tutorials.
This is an example from a 2D Game I made a while back, but i think it might help.
void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Destroyable")
{
Destroy(other.gameObject);
}
}
I used this to destroy certain blocks when the player would shoot them so many times, just switch them to the 3D Collider and Trigger, but it should do the trick for ya (i hope ^^).
edit: this script should be attached to your bullet prefab
Ok so I figured it out, it's kind of weird but apparently I was making the bullets move too fast... I had to slow down the "Bullet_Forward_Force" float to about 150f to make it work. Thanks to everyone who answered though.
I can't comment so I will make an answer:
You can make the bullet go fast, just set the collision detection to continious dynamic.
It has an almost %100 success rate.
Related
I'm trying to make a 3D racing game on Unity and I am currently looking to program checkpoints. Right now I have hit a roadblock in which I can't convert vector3 to collider. Any advice?
private void OnTriggerEnter3D(Collider Checkpoint)
{
if (Checkpoint.tag == "Checkpoint")
{
Checkpoint = transform.position;
}
}
Checkpoint is a Collider data type. Try it with Checkpoint.transform.position
A Collider is not at all a Vector3. I invite you to read the documentation for both types to understand better what each is used for.
As mentioned in another comment, if you want to access a Collider position, you should use Collider.transform.position (so
Checkpoint.transform.position
in your case). A Collider component should be attached to the object your rigidbody is supposed to collide to.
If you want the Collider to respond phisically to impacts, as mentioned in the documentation, you should attach a Rigidbody to it.
I am trying to make an attack mechanic for my 2D game. It would work as follows: if the player was standing in front of the enemy and pressed space the enemy would die. To do that I wrote this in the player script:
void Attack()
{
Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(AttackArea.position, AttackRange, EnemyLayers);
foreach (Collider2D enemy in hitEnemies)
{
enemy.GetComponent<Enemy_1>().Death();
}
}
And this in the enemy script:
public void Death()
{
Destroy(gameObject);
}
It worked flawlessly but I wanted to make another type of enemy to the game so I added this for the second enemy in the player attack script (I have mention that "GunBoi" is the name of the second enemy script and that I named the second function "Dead()" instead of "Death()" since I thought it wouldn't work if they had the same name)
Collider2D[] hitEnemies2 = Physics2D.OverlapCircleAll(AttackArea.position, AttackRange, EnemyLayers);
foreach (Collider2D enemy2 in hitEnemies2)
{
enemy2.GetComponent<GunBoi>().Dead();
}
and this in the second enemy script:
public void Dead()
{
Destroy(gameObject);
}
but whenever I try to attack the second enemy nothing happens. When I try to attack the first enemy it does work and the enemy dies. Does anyone know why this is happening?
About your problem: your code is in order. Check if the script have been assigned to the enemy prefab.
Now, a recommendation. If you follow it, your problem may be solved.
You said that you created a new script for the new enemy but they both share one same mechanics: the Death() function (and, as long as they are both enemies, i belive they will share a lot of other mechanics like HP, damage, and other traditional stuff).
In this case, i think that the best solution is to the GunBoi's script be inherited from the common enemy's one.
Replicate a function that do exactly the same thing but have a (not very) different name is a bad practice. If you decide to create a third enemy, you will have to create a third function to destroy it, but again, with a different name.
Multiple things could be wrong, but at first sight I would at least verify those two:
are the GunBoi on the good layer
Do they have the GunBoi component
We lack too much information to help you further than this.
But honestly you should try to refactor this by having both enemy type have a generic enemy component. There is no reason why should would have to do the collision logic twice. You want to have to write as less code as possible. With your approach you will have to do this for each new enemy type which is both problematic and error prone.
I'm a student and I'm doing a 2D platform game as a project but my programming skills are so bad(That's why I'm trying to do the code by myself) but I'm stuck on that and I don't really have an idea about whats going on. Let me explain.
I've got my Player GameObject with his script playerBehaviour actually working and a BoxCollider2D marked as a Trigger
This Player, also tagged as Player, it's inside a Trigger that belongs the the GameObject LiveZone, who has the DeathZone script below.
using UnityEngine;
using System.Collections;
public class DeathZone : MonoBehaviour {
public PlayerBehaviour playerBehaviour;
void OnTriggerExit2D (Collider2D other) {
if (other.tag == "Player") {
playerBehaviour.respawn = true;
Debug.Log ("Respawn");
}
Debug.Log ("Exit Collider");
}
}
I also tried to do it in a most common way, setting the limits of the "LiveZone" with some triggers to delimitate the area with "DeathZoneTriggers"(that's why the script was called DeathZone at first). But I had the same problem with the OnTriggerEnter2D ().
It looks like it doesn't want to detect my Player leaving or entering this area, as you can see I also called some Debugs, but are not working neither.
To organize information you may also need(or not):
2 GameObjects with Triggers
"Player", who has to exit the zone and "AliveZone", who should detect who's leaving.
Player is tagged as "Player", AliveZone has no tag(don't know if that would mean something)
Any idea?
God I found what was wrong, I set a layer that was ignoring the deafault ones, so it wasn't interacting with that deathzone collider ._.
At least I finally found what was wrong with it, thx anyways for those who read it up and tried to think about a solution! :)
I'm trying to write a script that allows the player to walk into a pack of ammo (or health) and gain something from doing so. I'm struggling with the actual collision part of this as no matter what I do I can't seem to get it to work. I currently have this script on my ammo pack object.
void onTriggerEnter(Collider collision) {
if (collision.gameObject.tag == "Player")
{
Debug.Log ("Collided");
}
}
My ammo pack object has a collider on it (currently capsule, will be box for final product) that has "Is Trigger" enabled.
My player has a capsule collider also (non-trigger) and a rigidbody with gravity enabled and everything else default. It is also tagged as "Player". When my player walks into the ammo pack, there is no message printed.
I've tried several solutions that involve changing triggers on colliders and rigidbody kinematic settings but none of them seem to work. I'm using Unity 5 and so I was wondering if I'm doing something wrong. Any help would be greatly appreciated.
This function will never get called because your capitalisation is wrong. Capitalise the first letter of the function name.
void OnTriggerEnter(Collider c)
Instead of:
void onTriggerEnter(Collider c)
Note: Always use CompareTag() instead of == to compare strings. Both work but CompareTag is GC friendly.
I have an object with a mesh collider and a prefab with sphere collider. I want the instance of the prefab to be destroyed if the two collide.
I wrote the following in a script:
private void OnCollisionEnter(Collision c)
{
if (c == target)
Destroy(transform.gameObject);
print("something"); // Doesn't get printed
}
But it is not working. I have tried toggling isTrigger on both the objects.
I had the same problem of OnCollisionEnter not being called and found this question.
For me, the problem was that I was making a 2D game so the answer is to use the OnCollisionEnter2D function instead.
Have a look at this table
If you want your OnCollisionEnter to be called make sure:
(a) Both objects have a collider attached.
(b) None of the objects is a trigger collider (this will issue OnTrigger function & not OnCollisionEnter)
(c) One of the objects (doesn't matter which of them) is a rigid, non kinematic & non static object (the second don't have to be a rigid body).
(d) Due to computational difficulties MeshCollider might have hard times colliding with other mesh collider, use them with caution.
(e) Make sure both the objects are in the same layer (or at least that they collide in scene settings).
(f) If you are working in 2d - OnCollisionEnter2D will be called, rename your function.
Make sure one of them has a non-kinematic rigidbody attached. Taken from the Unity docs:
When a collision between two Colliders occurs and if at least one of them has a Rigidbody attached, three collision messages are sent out to the objects attached to them. These events can be handled in scripting, and allow you to create unique behaviors with or without making use of the built-in NVIDIA PhysX engine.
From here: Unity3D MeshCollider
I had a similar problem. The box collider wasn't as big as the collision object. Setting the x and z values to 2 units fixed the problem!
Have you tried using the OnTriggerEnter() method and setting a collider on the object to a trigger?
If it doesn't need to tell what object its colliding with you could do a simple
void OnTriggerEnter(){
Destroy(transform.gameObject);
}
Edit:
Also I have done OnCollision like this
private string hitobject;
void OnCollisionEnter(UnityEngine.Collision hit)
{
hitobject = hit.gameObject.tag;
if(hitobject == "Plane")
{
isgrounded = true;
}
}
None of the objects are triggers and they don't need rigid bodies to work.