Hello,
I instantiate an apple object from an apple_prefab this way:
apple=Instantiate(apple_prefab, new Vector 3…etc);
Now I want to access a variable is_edible which is located in a script in the apple_prefab, named also “apple”, and change it to “true”, so I do the following:
apple.GetComponent().is_edible=true;
So far so good.
What I want to do is to retrieve that script without directly typing “apple” between the < >. Since the instantiated object has the same name as the script, I tried things like:
string name=apple.name;
apple.GetComponent(name).is_edible=true;
But it doesnt work.
Ok, I will try.
Imagine a projectile. When that projectile hits a box, that box loses damage equal to a damage value “damage_value” stored in a script in the object “projectile”.
The script of the projectile looks like:
public float damage_value= 2f;
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.layer == LayerMask.NameToLayer("boxes"))
{
collision.gameObject.GetComponent<Chest>().damage_taken = damage_value;
}
}
So basically when the projectile hits an object in the layer “boxes”, it tells the hit object to change its value “damage_taken” to “damage_value”. In the case above, I used the word “Chest” because I know that the object being hit in the scene is a chest (which is in the layer of boxes), which has a script component named “Chest”. But instead of a specific word, I would like the code to automatically find the script component associated with the hit object.
I see. So you have many different objects, all of which can take damage, so you don’t want to specifically use “Chest”, because it could be some other type.
There are two straightforward approaches I would recommend to make this more generic.
The first way is creating a component that handles health or damage, and you put that on any objects that are damageable, for example:
public class DamageHandler : MonoBehaviour
{
public float health;
public void TakeDamage(float damage)
{
health -= damage;
if (health <= 0)
{
health = 0;
Destroy(gameObject);
}
}
}
The second way is to use an interface, which defines some function signatures. Any class that implements that interface is required to have those functions:
public interface IDamageable
{
void TakeDamage(float damage);
}
Then implement that interface on the Chest, or any other class that should be able to take damage, for instance:
public class Chest : MonoBehaviour, IDamageable
{
public float health = 1;
public void TakeDamage(float damage)
{
health -= damage;
if (health <= 0)
{
health = 0;
Destroy(gameObject);
}
}
}
Then get the interface in the collision:
// get a component that implements IDamageable
IDamageable damageHandler = collision.gameObject.GetComponent<IDamageable>();
if (damageHandler != null)
{
damageHandler.TakeDamage(damage_value);
}