I want gameObject1 to get destroyed after it collides with gameObject2.
gameObject1 is a non-kinematic rigid body and a nav agent with its destination being gameObject2, while gameObject2 is an empty object. Both of them have box colliders, and neither has Is Trigger on. gameObject1 succeeds in going towards gameObject2; however, they don't seem to be colliding. Instead of being destroyed, gameObject1 doesn't stop moving. What went wrong?
void OnCollideEnter(Collision col)
{
if (col.gameObject.tag == "deleter")
{
Debug.Log("triggerdel"); //this doesn't show up on console.
Destroy(gameObject);
}
}
Commenters have suggested using OnCollisionEnter, which is a Unity Message that is called whenever things collide. What you have now is not a Unity Message so it will never be called.
As an aside, it's a good idea to use OnCollisionStay instead. OnCollisionStay is called every single frame the object is being collided with, so in case of any bug the object will destroy in the next frame. OnCollisionEnter is only called for one frame, so if something goes wrong (which is very unlikely), the object will try to be destroyed again in the next frame.
Related
My problem looks like this:
I have one stationary object wall and second object that is moving projectile. I want projectile to stop when it collides with wall. But ewery my attempt ended with projectile passing through wall.
Only script that affects movement of projectile:
public Transform trans;
void Update()
{
trans.Translate(0, 0, speed * Time.deltaTime, Space.Self);
}
All compomponents of projectile:
All components of wall:
Note: I have correctly set up layers in project settings.
I have tried many combinations of rigit boddies, colliders, layers and so on, but projectile always passed through wall.
In general, your presented setup is right. The contacting object have a Rigidbody component, and the objects you can collide have at least a collider (not a trigger).
First possible problem: your Rigidbody is set to Kinematic. Did you enable all collision modes in Project Settings > Physics > Contact Pairs Mode?
Second problem is the use of transform.Translate in the Update. Translate will ignore physic and just move the object when you tell it to do, and Update may be out of sync with the physic loop, where it would be recommended to use FixedUpdate. Even using FixedUpdate, Translate will not do the right job. It will force the object to move and the physic can complain or not about that (it can move the object back, glitching, or it can just ignore and let the object pass).
The right way to move a Kinematic rigidbody is through rigidbody.MovePosition, as stated in the Unity docs. For non-kinematic objects, you can use AddForce. Some tutorials also teach to set velocity of Rigidbody, which is not recommended because it can have undesired effects. Do it if you know the side effects and really want them.
I had a similar issue before. May I suggest destroying the projectile instead? You will then have to use OnCollisionEnter().
First, create a script and attach it to your projectile game object. After that, give your wall a tag, like 'wall'. Then, do something like this:
void OnCollisionEnter(Collision collision)
{
// Gets information about the game object the projectile collided with
GameObject objectCollided = collision.gameObject;
if (objectCollided.tag == "wall'){
// Do something with either the wall/enemy
}
// Destroy the projectile
Destroy(gameObject);
}
Note: If the intent was not to destroy the projectile but rather sticking to the wall, I suggest you to use detect collision using Raycast. Raycast has a hitInfo parameter and stores information about a gameObject that it hit, as well as the where did the Ray hit the gameObject.
Thus you can use this to move your projectile accordingly. In my previous projects, I used the Rigidbody component of my projectile and used .AddForce() to shoot it out, then detect collision with OnCollisionEnter().
Maybe you could do the same, but have a separate function to remove that force on entering a collision. I never tried it so I do not know if it will work.
Transform.Translate overrides the physics engine of unity. If you want to take advantage of the rigidbody and collider components of your gameObjects, you need to use rigidbody.Velocity or (as unity recommends in the docs) rigidbody.AddForce, and make sure you set IsKinematic to False on both rigidbodies, so that they can interact with one another physically.
i made a "turret" in unity that shoots automatically on enemies it works with one enemy but when i put 2 it shoots in the midle of then dont know why it does that
public transform enemy;
public void Update() {
enemy = Gameobject.FindgameObjectWithTag("Enemy").getComponent<Transform>;
//just put the getting the possition part because the shooting works just fine
}
Your script is refreshing the enemy position every Update() iteration.
Try to have the turret stick to the enemy until it gets out of range, or until it is dead. Before doing your variable assignation, check if enemy != null, if it is the case, then you can write :
enemy = Gameobject.FindgameObjectWithTag("Enemy").getComponent<Transform>;
Also, try to avoid refreshing every Update() call, instead, use a different function that you call every half second.
I recommend you checking this project by Brackeys, that handles the situation perfectly. Here
GLHF
I'm making a endless shooter game, where the bullet is just a object that goes forward until it hits something.
The enemies all have a script with an HP.
I want to know if it's to expensive to do:
void OnCollisionEnter2D(Collision2D collision) {
if(TagsAndHashes.IsTagEnemy(collision.transform.tag))
DamageHandler.CauseDamage(collision.gameObject.GetComponent<EnemyBehavior>());
}else{
pool.ReturnObject(gameObject);
}
This way I would be calling GetComponent<EnemyBehavior>() every time a player shoots an enemy.
Is it too costly or is it fine?
The game is for mobile.
Thanks.
It would be more logical and less costly to flip who is responsible for damage here.
Have a script on the enemy that detects collisions.
Have that method check the tag of the object which is colliding with it.
Then use the script already on the enemy gameobject to issue damage to itself.
This way the script does not have to go and get a reference for the other object which is of course expensive. Instead it just talks to itself... like I do.
Hope it helps.
I'm making a game in unity for a school project. I'm stuck on this one part where I want a block to fall and be destroyed once a player has touched the block and moved to the next. Having so much trouble and would love some assistance.
The concept of what i'm aiming for can be seen here: http://www.coolmath-games.com/0-b-cubed
On each block, you'll need to attach a script which contains the OnCollisionExit () method (reference). Pass in the collision parameter (see reference) and use the collision info to confirm that the object leaving the collider is the player (eg tag the player with a player tag in the inspector and check the collision's collider's tag).
In this method, place your code for making the block fall.
Make sure you've added colliders to your objects so that they interact. If you run into problems, post back some code and I'll get back to you.
Actually you do not need to detect collision here. It is not neccessary. Just compare base cube position with player cube position in x,z plane (there should be only difference in Y-axis since player cube is over base cube). No need for collsions here. Than you attach script to all base cubes checking for playercube to hover other them (position check) and than on playercube next movement you attach rigidbody to basecube and destroy it after a second. Simple:)
EDIT
The code should look like this. More or less.
GameObject playerCube; //this is reference to Player object
bool playerEnter = false;
bool playerLeft = false;
void Start()
{
playerCube = Gameoject.Find("PlayerCube"); // here you put the name of your player object as a string. Exactly as it is in the hierarchy
}
void Update()
{
if(playerCube.transform.position.x == transform.position.x && playerCube.transform.position.z == transform.position.z)
{
playerEnter = true; // this checks if player stepped on the cube
}
if((playerCube.transform.position.x != transform.position.x || playerCube.transform.position.z != transform.position.z) && playerEnter == true && playerLeft == false) //checks if player left the cube
{
playerLeft = true; // we do this so the code below is executed only once
gameObject.AddComponent<Rigidbody>(); // ads rigidbody to your basecube
Destroy(gameObject, 1.0f); //destroys baseCube after one second
}
I think that more or less that should do it. In the final game I probably would use coroutines for your task. Also you need to think how do you check if the cube already was destroyed, I mean how will your game detect if player can step on the next cube - does it exist or not?
EDIT 2
Hard to tell what will work or not without your hierarchy, your code and knowing what do you want to have exactly. Study this code - it will work after some adjustments to your needs
I'm trying to have my game spawn enemies when ever the player reaches a way point.
Right now, I have this functionality working. When my player gets to the first way, the enemies spawn. He only moves on once he has killed all of the enemies on the screen are dead. However, when he gets to the second way point, no enemies spawn.
Right now, in my collision class I call the following line of code:
Destroy(gameObject)
Whilst this work for the first way point, the second one wont spawn anything as the game object my collision class has been attached to has been destroyed. However, all of my enemies are prefabs and I thought the destroy function would only destroy that instance of the prefab. No matter when you called the instantiate method, it would only destroy that instance.
I'm spawning my enemies with the following method:
public GameObject SpawnEnemies()
{
Vector3 _position = new Vector3(transform.position.x, transform.position.y, transform.position.z);
// instantiate particel system
Instantiate(_particle, _position, Quaternion.identity);
_clone = (GameObject)Instantiate(_enemy, _position, transform.rotation);
_ai = _clone.GetComponent<HV_BaseAI>();
_ai._waypoints = _wayPoints;
return _clone;
}
Then I'm finding out how many of the enemies are still alive with the following code in my collision method:
GameObject g, f; // enemies I want to spawn
g = GameObject.FindGameObjectWithTag("SectionController");
f = GameObject.FindGameObjectWithTag("SectionController");
HV_SectionController tempSectionControllerGroundEnemies, tempSectionControllerFlyingEnemies;
tempSectionControllerGroundEnemies = g.GetComponent<HV_SectionController>();
tempSectionControllerFlyingEnemies = f.GetComponent<HV_SectionController>();
tempSectionControllerGroundEnemies._numberOfGroundEnemies.Remove(gameObject); // remove enemies from list
tempSectionControllerFlyingEnemies._numberOfFlyingEnemies.Remove(gameObject);
//Destroy(gameObject);
_numberOfGroundEnemies = tempSectionControllerGroundEnemies._numberOfGroundEnemies.Count;
_numberOfFlyingEnemies = tempSectionControllerFlyingEnemies._numberOfFlyingEnemies.Count;
Then when I want to move on I do the following check:
if (_groundEnemiesRemaining == 0)
{
MoveToNextSection();
_sectionStartTime = Time.time;
}
i know the above line is checking only one type of enemy at the moment, but its the ground enemies I'm having issues with at the moment.
Does anyone know how I can delete the enemy prefab I'm spawning from my first section, once they've been hit, then have it respawn at the next section without the error:
The object of type 'GameObject' has been destroyed but you are still
trying to access it.
My guess would be that the gameobjects are being "destroyed" by two different collision events. First one destroys it, second throws the error.
What I've done in similar situations is put the Destroy code within the object being destroyed. Then from within your collision class, use gameObject.SendMessage(string) to send a message to the actual object, which destroys it.
Without seeing further code I can't speculate as to the origin of the error, but the above is my best guess. SendMessage can also take a DontRequireReceiver parameter, so it won't pop an error if two collision events try to send it a message.
Instead of destroying them u can just disable them using gameObject.SetActive() !