Best way to get information with prefabs

Hey guys. I am currently working on an FPS game, and I have setup my enemy and my player to talk to each other. However, I am having a problem, because my enemy is a prefab, which I am instantiating throughout the game. Becuase of this, I cannot find a way to have all of my prefabs to do damge to my player. I am setting a private health variable inside of my player script equal to a public playerHealth value inside my enemy script (my player script deals with death and such). Any help on this topic would be great.

Player Script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PlayerHealth : MonoBehaviour
{
    public int health = 100;
    GameObject zb;
    EnemyController ec;

    //public Image gameOver;
    public Image crossHair;
    void Start()
    {
        zb = GameObject.Find("Zombie");
        ec = zb.GetComponent<EnemyController>();
      
    }

    void Update()
    {
        health = ec.playerHealth;

        if(health <= 0)
        {
            GameOver();
        }
    }

    void GameOver()
    {
        crossHair.enabled = false;
        Time.timeScale = 0;
       
    }


}

Enemy Script:

using UnityEngine;
using UnityEngine.AI;
public class EnemyController : MonoBehaviour

{
    public float lookRadius = 10f;

    private float zombieHealth;

    public Animator zombieAnimation;

    public float cooldown = 1f;
    private float lastAttackedAt = -9999f;


   
    

    public int damage = -20;
    private GameObject playerInfo;
    public int playerHealth;

    Transform target;
    NavMeshAgent agent;



    // Start is called before the first frame update
    void Start()
    {
        target = PlayerManager.instance.player.transform;
        agent = GetComponent<NavMeshAgent>();
        playerInfo = GameObject.Find("FirstPersonPlayer");
        PlayerHealth ph = playerInfo.GetComponent<PlayerHealth>();
        playerHealth = ph.health;
    }

    // Update is called once per frame
    void Update()
    {
       
       zombieHealth = GetComponent<Target>().health;
       float distance = Vector3.Distance(target.position, transform.position);
       

        if (distance <= lookRadius && zombieHealth > 0)
        {
           
            agent.SetDestination(target.position);
            zombieAnimation.SetBool("walking", true);
            zombieAnimation.SetBool("attacking", false);

            if (distance <= agent.stoppingDistance + .3)
            {
                zombieAnimation.SetBool("attacking", true);
                FaceTarget();
                if(Time.time > lastAttackedAt + cooldown)
                {
                    Attack();
                    lastAttackedAt = Time.time;
                }
               
              
            }
           

        }

    }

    void FaceTarget()
    {
        Vector3 directon = (target.position - transform.position).normalized;
        Quaternion lookRotation = Quaternion.LookRotation(new Vector3(directon.x, 0, directon.z));
        transform.rotation = Quaternion.Slerp(transform.rotation, lookRotation, Time.deltaTime * 5f);
    }

    void Attack()
    {
        playerHealth += damage;
        Debug.Log(playerHealth);
    }

    void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(transform.position, lookRadius);
    }
}

You would need to overwork your scripts since you shouldnt store the playerHealth in the EnemyController,
you should just access it … ,

also we would need a bit more info about the meaning of this setence:

Becuase of this, I cannot find a way to have all of my prefabs to do damge to my player.

how are you doing damage to the player if it work?
Or How do you want todo damage to your player?

The reason I’m storing the playerHealth variable inside of my EnemyController script is becuase that’s how I am going about doing damge. If there is a way I can add or subtract the value of my variables in my PlayerHealth script from my EnemyController, that would fix all of my problems.

And to answer your question, I could have 1 enemy attacking you, or I could have 50 enemies attacking you… you are only going to have 20 health removed from you at a contanst rate (of 1 second).

Well, how about

GetComponent<YourScript>().getHealth();

you shouldnt store the playerHealth seperatley , since your “player” wont even notice if he dies if you do it like so, to decrease the Health of your Player,
you should just create a function

void TakeDamage(float damageAmount)

and call it where ever its needet

Inside of the GetComponent<>() method, wouldn’t I need to use GameObject.Find()? Since my two scripts are on different GameObjects?

First we need to know, how are you going about doing damage?

  • OnCollision?
  • OnButtonClick?
  • etc…
1 Like

The issue is the player is setting its health to the ‘zb’ EnemyController.playerHealth, so it will only work for the one zombie that it finds on Start.

The short fix for accessing other GameObjects is to make the enemy do target.GetComponent<PlayerHealth>().health += damage;, instead of having PlayerHealth constantly set itself to ec.playerHealth.

The longer fix is that you should split Health into its own component that you put on the player and the enemies, then the spawned enemies just have to do these steps:

  • Assign something as Target. (you are already doing)

  • Move to the Target (you are already doing this)

  • When close, access the Health script on the Target var targetHealth = Target.GetComponent<Health>(); and call targetHealth.TakeDamage(20).

Even better, the Target would just be of type Health, and assign it with Target = GameObject.Find("FirstPersonPlayer").GetComponent<Health>();.

Damage is supposed to be taken whenever the enemy is within a certain distance from the player.

Alright. I’ll try some the things you listed. For some reason, I didn’t think about using the target variable I created.

What you are trying to get me to do won’t work because my Target health is strictly for my guns. Could I do this, and just use a different variable name?

it will work you just have to do it :smile:,

you basically have to declare a function in your “Gun” Component which will do damage to the enemy, as a parameter you need the enemy,

now it depends on your code which we haven’t seen yet, how you approach to get the enemy,

but you can do basically something like this:

void damage(GameObject target)
{
   target.GetComponent<Health>().health -= weaponDamage;
}

(Sry for the Syntax errors, I’ve written the code in the browser editor)

Edit: As i can see also you wrote “can i use another variable name” … ofc, what we are typing here are just recommendations which you can modify as you want

Nevermind, I see what you are saying. Thanks!