- Home /
Copy of GameObject gets destroyed instead of GameObject itself
Hey guys. I have a little problem which i cant really get behind even though its probably not a hard one. I have two walls (one is a copy) and if i damage the original one, the damage gets inflicted onto the copy and then ,after it recieves enough damage, the copy gets destroyed, even though i tried to damage the original. Heres a video of that happening: The Video
Anyway I have a "ObjectHealth" Script which is basically a very simple and normal health script with a certain life value which can get reduced and if reached zero the gameObject gets destroyed. Heres the Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObjectHealth : MonoBehaviour
{
public float maxHealth = 200f;
public float currentHealth;
public GameObject deathEffectOne;
public bool isDead = false;
public GameObject objectLOL;
void Start()
{
currentHealth = maxHealth;
Debug.Log(currentHealth);
}
public void TakeDamage(float amount)
{
currentHealth = currentHealth - amount;
if (currentHealth <= 0)
{
Die();
}
}
void Die()
{
DeathEffect(deathEffectOne);
Destroy(objectLOL);
isDead = true;
}
public void DeathEffect(GameObject deathEffect)
{
Instantiate(deathEffect, transform.position, transform.rotation);
}
}
Would be nice if anyone could help :)
Answer by Anox · Mar 03 at 09:19 AM
[Updated Answer] Hey there,
You should get the reference to the Wall ObjectHealth script from the Object you collided with:
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.tag == "Wall")
{
Instantiate(wallImpactEffect, transform.position, transform.rotation);
BulletExplosion(impactEffectOne);
ObjectHealth otherObjectHealth = collision.gameObject.GetComponent<ObjectHealth>();
otherObjectHealth.TakeDamage(damage);
Destroy(gameObject); //Thats for the bullet itself
}
}
This following part is problematic because you have multiple objects with tag "wall" and call a function which only returns you one instance:
private ObjectHealth oH;
void Start()
{
oH = GameObject.FindGameObjectWithTag("Wall").GetComponent<ObjectHealth>();
}
Here is another answer that explains how to get a script from the gameobject you collided with: https://answers.unity.com/questions/948013/get-a-game-objects-reference-from-collision.html
Yeah i think the problem is that the damage itself gets inflicted to the copy somehow but i dont know why. I double checked the inspector the objectLOL assignment is ok. I call the takeDamage method in my bullet script, it goes like this:
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.tag == "Wall")
{
Instantiate(wallImpactEffect, transform.position, transform.rotation);
BulletExplosion(impactEffectOne);
oH.TakeDamage(damage);
Destroy(gameObject); //Thats for the bullet itself
}
}
Shouldnt the damage get inflicted on the wall thats being hit?
Here you call the Script "oH" to take Damage.
You could do something like this to dynamically get the correct ObjectHealth script from the object you collided with:
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.tag == "Wall")
{
Instantiate(wallImpactEffect, transform.position, transform.rotation);
BulletExplosion(impactEffectOne);
ObjectHealth otherObjectHealth = collision.gameObject.GetComponent<ObjectHealth>();
otherObjectHealth.TakeDamage(damage);
Destroy(gameObject); //Thats for the bullet itself
}
}
Ah and i forgot: Thats how i get access to the ObjectHealth Script (its called "oH" in my BulletScript):
private ObjectHealth oH;
void Start()
{
oH = GameObject.FindGameObjectWithTag("Wall").GetComponent<ObjectHealth>();
}
Is something wrong with getting access trough the tag? And also i made a little discovery. The newest copy that i make always gets the damage inflicted to it and then the damage goes to the second youngest one and so on..
There isn’t anything wrong with using tag but you have to consider that you might have more than one object with this tag.
I’m not sure about the design of your overall project but I wouldn’t manage health like this.
What is the variable ObjectHealth and why fo you need a class for this? Does it need to be that complex?
I suggest a simple redesign.
Your wall should have a simple health integer variable that’s going to decrease when hit.
To do that, I’d put the collision event on the wall itself and if a collision happen, then you check the source of the damage. The object « tag » can do that if you want. For example, check if the tag is « projectile « instead and then, you’ll have access to the healt value directly in your collision event and decrease it there. This way, you ensure that this is the wall that’s going to be hit and make all the effect and other stuff from there as well.
This should simplify the design a lot and make it easier to manage and avoid bugs like this.
Imagine your game on a larger scale, if you add if for all type of tag that you can hit and so on, this is going to be a very long script very fast.
Better have a wall script that manage his own property than the other way around.
If you game has more than one type of object that can be like a wall, you could have a script named « destroyableobject » for example that you can attach to those kind of object and they will all behave the same way. That way, you don’t have to add another tag type to your collision.
Both pots, walls, and other object can be hit by « projectile » for example, so they all use the same condition, but if the projectile do the comparison, then it needs to specify all of them one by one.
Not sure if that’s clear? I’m typing this on my phone :P
Hello! I think that it might be a mistake to tell this person their architecture is wrong, given that (as you say) you don't know the design or scale of their project. There are lots of cases where it might be perfectly sensible to have an ObjectHealth class like this.
GameObject.FindGameObjectWithTag("Wall")
This is the problem. You are using global "GameObject" to find an object with tag "wall". If you have 2 Objects with tag "wall" you are always getting the first one.
I replied inside another comment as to how you can dynamically get the correct script :)
Cheers.
As a side note:
Why is there no reference to this method in the API docs? link text
I can find FindGameObjectsWithTag which returns an Array (hence the "S" after Object) but not the singular FindGameObjectWithTag.
Anyone know why?
Yup, that worked :) I now manage the Collision in the ObjectHealth script. I did it like this: using System.Collections; using System.Collections.Generic; using UnityEngine;
public class ObjectHealth : MonoBehaviour
{
public float maxHealth = 150f;
public float currentHealth;
public GameObject impactEffect;
public GameObject destructionEffect;
private void Start()
{
currentHealth = maxHealth;
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.tag == "Bullet")
{
Instantiate(impactEffect, transform.position, transform.rotation);
currentHealth -= 50f;
if (currentHealth <= 0)
{
Destruction();
}
}
}
private void Destruction()
{
Instantiate(destructionEffect, transform.position, transform.rotation);
Destroy(gameObject);
}
}
Thanks for giving me the advice!
Glad it could help. I should have posted this as an answer if it solved it :)
Answer by drizztdourden_ · Mar 03 at 09:47 PM
Hard to say. I’d say that most likely the problem lies on how you create the copy.
It might be that it is a reference and hence goes back to the original object instead.
Are you familiar with the concept of reference vs value in C#? That’s what I would look into. I’m not in unity right now but ai believe you can probably use « .clone » to create a new value of your wall.
Yeah, i tried to make a whole new object and added everything that my wall already has to it but still, if i attacked the original wall the damage went to the newly made object, even tho its not a exact copy.
Your answer
Follow this Question
Related Questions
OnTriggerEnter2D doesnt work? 1 Answer
How to activate an object after another is deactivated 1 Answer
How to make sounds louder if I go faster 1 Answer
2D sprite wavering 0 Answers