Since my enemies are in a prefab they don't lose health
Hello guys ! I am making a game, and I have a player you can translate on enemies to kill them but since the foes are instantiate with a prefab and a spawnpoint I can't hit them. Maybe because the health isn't in an array. But I can't manage to do it. The foe Health is from there script.
GameObject GestureAttack()
{
//Get all the foes
GameObject[] Foes = GameObject.FindGameObjectsWithTag("Foe");
GameObject closest = null;
float distance = Mathf.Infinity;
Vector3 position = transform.position;
//Find the nearest to attack him
foreach (GameObject go in Foes)
{
Vector3 diff = go.transform.position - position;
float curDistance = diff.sqrMagnitude;
if (curDistance < distance)
{
closest = go;
distance = curDistance;
}
}
if (recupgeste == "ga_circle_01" && recupgestescore > 0.60 || Input.GetKeyDown(KeyCode.Space)) {
transform.position = Vector3.MoveTowards(transform.position, closest.transform.position, 100);
}
return closest;
//THE PROBLEM
//For each foe I have I hit them once (FoeHealth is the script (In start: FoeHealth = Foe.GetComponent<s_EnnemyControl>();)and currentHealth the life variable in the script).
foreach (GameObject go in Foes)
{
if (FoeHealth.currentHealth > 0 /*attackphas*/)
{
Debug.Log("TOOOK");
// ... damage the player.
FoeHealth.TakeDamage(attackDamage);
}
}
}
Thanks in advance ^^
Answer by Ulci · May 02, 2016 at 04:55 PM
So there is only a single instance of FoeHealth? You better create a new script which contains a field health and attach it to your prefab. Then you implement a TakeDamage method and you could access it like this: Foes[0].GetComponent().TakeDamage(5); This way you have a health variable for each foe and you only modify the value for the selected game object.
Answer by Torigas · May 02, 2016 at 04:03 PM
When you instantiate your prefabs you will see a gameobject in your scene window. Thus, unless you're using static variables your health values will change.
I'm not sure what your FoeHealth is, but it appears as if you're trying to use static methods on a class and not on an instance.
foreach (GameObject go in Foes)
{
FoeHealth fh = go.GetComponent<FoeHealth>();
if(fh!=null && fh.currentHealth > 0)
{
Debug.Log("TOOOK");
// ... damage the player.
fh.TakeDamage(attackDamage);
}
}
You need to access specific components of a GameObject and not try some arbitrary function calls on a Class. Hard to debug your code if you don't post essentials like "FoeHealth" ;)
Answer by deglet · May 03, 2016 at 10:28 AM
I didn't understand, this are my two scripts (sorry for the tab and coms):
using UnityEngine;
using UnityEngine.UI;
using PDollarGestureRecognizer;
public class s_PlayerControl : MonoBehaviour
{
//--------------------------------------------VAR------------------------------------
public GameObject Player = GameObject.Find("o_player");
public GameObject Foe;
public GameObject[] FoePos;
public float FoePosy;
//Recup Geste
public bool reco;
public string recupgeste;
public float recupgestescore;
public bool SymbolD;
public float PosXFoe;
public float PosZFoe;
// public float target;
//Vector3 FoePos = new Vector3(0, 0, 0);
public float speed;
s_EnnemyControl FoeHealth;
public int attackDamage = 1;
s_PlayerControl playerHealth;
//Swipe:
//float MinSwipeLength = 2000;
bool trackSwipe = false;
bool move = true;
public Vector2 firstPressPos;
public Vector2 secondPressPos;
public Vector2 currentSwipe;
public Vector2 currentSwipe2;
public Rigidbody player;
//Vie:
public int startingHealth = 3;
public int currentHealth;
private bool isDead;
private bool damaged;
public Slider Hearth_Slider;
public Image Flash_Image;
public float flashSpeed = 55f;
public Color flashColour = new Color(1f, 0f, 0f, 0.1f);
//Provisoire:
public s_EnnemyControl[] Script;
//--------------------------------------------START------------------------------------
void Start()
{
//Player
player = GetComponent<Rigidbody>();
//Gesture
reco = GameObject.Find("Finger").GetComponent<s_GestureFinger>().recognized;
// SymbolD = GameObject.Find("Finger").GetComponent<s_GestureFinger>().SymbolD;
//Vie:
currentHealth = startingHealth;
move = true;
Foe = GameObject.FindGameObjectWithTag("Foe");
FoeHealth = Foe.GetComponent<s_EnnemyControl>();
//FoePos = GameObject.FindGameObjectWithTag("Foe");
}
//--------------------------------------------UPDATE------------------------------------
void Update()
{
Swipe();
GestureAttack();
Damaged();
// Debug.Log(damaged);
recupgeste = GameObject.Find("Finger").GetComponent<s_GestureFinger>().recupgeste;
recupgestescore = GameObject.Find("Finger").GetComponent<s_GestureFinger>().recupgestescore;
PosXFoe = GameObject.Find("o_foe").GetComponent<s_EnnemyControl>().PosXFoe - 2;
PosZFoe = GameObject.Find("o_foe").GetComponent<s_EnnemyControl>().PosZFoe - 2;
// Foe.transform.position = FoePos;
}
//--------------------------------------------FUNCTIONS------------------------------------
void Swipe()
{
if (move == true)
{
//----SWIPE----
if (Input.touchCount > 0)
{
var touch = Input.GetTouch(0);
switch (touch.phase)
{
case TouchPhase.Began:
firstPressPos = new Vector2(touch.position.x, touch.position.y);
trackSwipe = true;
break;
case TouchPhase.Moved:
secondPressPos = new Vector2(touch.position.x, touch.position.y);
currentSwipe = new Vector3(secondPressPos.x - firstPressPos.x, secondPressPos.y - firstPressPos.y);
currentSwipe2 = currentSwipe;
break;
case TouchPhase.Ended:
currentSwipe.Normalize();
trackSwipe = false;
float Z = currentSwipe.y;
if (currentSwipe2.magnitude > 100 && recupgestescore < 0.60)
{
// Player.transform.Translate(currentSwipe.x * 10, 0, Z * 10);
player.AddForce(currentSwipe.x * 10, 0, Z * 10, ForceMode.Impulse);
}
break;
}
}
}
}
GameObject GestureAttack()
{
GameObject[] Foes = GameObject.FindGameObjectsWithTag("Foe");
GameObject closest = null;
float distance = Mathf.Infinity;
Vector3 position = transform.position;
foreach (GameObject go in Foes)
{
Vector3 diff = go.transform.position - position;
float curDistance = diff.sqrMagnitude;
if (curDistance < distance)
{
closest = go;
distance = curDistance;
}
}
if (recupgeste == "ga_circle_01" && recupgestescore > 0.60 || Input.GetKeyDown(KeyCode.Space)) {
transform.position = Vector3.MoveTowards(transform.position, closest.transform.position, 100);
}
return closest;
foreach (GameObject go in Foes)
{
if (FoeHealth.currentHealth > 0 /*attackphas*/)
{
Debug.Log("TOOOK");
// ... damage the player.
FoeHealth.TakeDamage(attackDamage);
}
}
}
void Damaged()
{
if (damaged)
{
Flash_Image.color = flashColour;
}
else
{
//Transition de la couleur vers la normale
Flash_Image.color = Color.Lerp(Flash_Image.color, Color.clear, flashSpeed * Time.deltaTime);
}
damaged = false;
}
public void TakeDamage(int amount)
{
damaged = true;
currentHealth = currentHealth - 1;
Hearth_Slider.value = currentHealth;
if (currentHealth <= 0 && !isDead)
{
Death();
}
}
void Death()
{
isDead = true;
// Debug.Log(isDead);
move = false;
//GUI.Label(new Rect(Screen.width - 100, 10, 100, 30), "Restart Level");
// Application.LoadLevel(Application.s_scene01);
}
}
and
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class s_EnnemyControl : MonoBehaviour
{
//Ennemi positionement
//Ne pas mettre le Transform en public ou private sinon l'ennemi ne trouve pas le joueur.
NavMeshAgent nav;
Transform o_player;
GameObject player;
public float PosXFoe;
public float PosZFoe;
public float sinkSpeed = 2.5f;
bool isSinking;
//Attack
public float timeBetweenAttacks = 1f;
public int attackDamage = 1;
s_PlayerControl playerHealth;
bool playerInRange;
float timer;
//s_EnnemyControl enemyHealth;
s_EnnemyControl FoeHealth;
//Vie
public int startingHealth = 1;
public int currentHealth;
public int scoreValue = 10;
bool isDead;
CapsuleCollider capsuleCollider;
public int score; // The player's score.
public Text text;
public int Points = 21;
//---------------------------------------------START---------------------------------------------
void Start()
{
o_player = GameObject.FindGameObjectWithTag("Player").transform;
player = GameObject.FindGameObjectWithTag("Player");
nav = GetComponent<NavMeshAgent>();
playerHealth = player.GetComponent<s_PlayerControl>();
capsuleCollider = GetComponent<CapsuleCollider>();
//Vie
currentHealth = startingHealth;
// text = GetComponent<Text>();
// Reset the score.
score = 0;
}
//---------------------------------------------UPDATE---------------------------------------------
void Update()
{
nav.SetDestination(o_player.position);
PosXFoe = transform.position.x;
PosZFoe = transform.position.z;
//Debug.Log(currentHealth);
// if (Input.touchCount > 0 && Touch.position == Foe) {
// Debug.Log("yo");
//}
//HYPOTETIC ERROR
// Add the time since Update was last called to the timer.
timer += Time.deltaTime;
// If the timer exceeds the time between attacks, the player is in range and this enemy is alive...
if (timer >= timeBetweenAttacks && playerInRange && currentHealth > 0)
{
Attack();
}
if (playerHealth.currentHealth <= 0)
{
}
if (isSinking)
{
// ... move the enemy down by the sinkSpeed per second.
transform.Translate(-Vector3.up * sinkSpeed * Time.deltaTime);
}
text.text = "Score: " + score;
}
//---------------------------------------------FUNCTIONS---------------------------------------------
void OnTriggerEnter(Collider other)
{
// If the entering collider is the player...
if (other.gameObject == player)
{
// ... the player is in range.
playerInRange = true;
}
}
void OnTriggerExit(Collider other)
{
// If the exiting collider is the player...
if (other.gameObject == player)
{
// ... the player is no longer in range.
playerInRange = false;
}
}
void Attack()
{
// Reset the timer.
timer = 0f;
// If the player has health to lose...
if (playerHealth.currentHealth > 0 /*attackphas*/)
{
// ... damage the player.
playerHealth.TakeDamage(attackDamage);
}
}
public void TakeDamage(int amount)
{
// If the enemy is dead...
if (isDead)
// ... no need to take damage so exit the function.
return;
currentHealth = currentHealth - 1;
// If the current health is less than or equal to zero...
if (currentHealth <= 0)
{
// ... the enemy is dead.
Death();
}
}
void Death()
{
// The enemy is dead.
isDead = true;
GetComponent<NavMeshAgent>().enabled = false;
GetComponent<Rigidbody>().isKinematic = true;
isSinking = true;
// transform.Translate(-Vector3.up * sinkSpeed);
// Turn the collider into a trigger so shots can pass through it.
capsuleCollider.isTrigger = true;
Debug.Log("He is dead");
// Tell the animator that the enemy is dead.
// anim.SetTrigger("Dead");
Destroy(gameObject, 2f);
// Change the audio clip of the audio source to the death clip and play it (this will stop the hurt clip playing).
// enemyAudio.clip = deathClip;
// enemyAudio.Play();
// S_ScoreControl.score;
score += Points;
}
}
Your code is quite hard to read and you have way too many variables and bad na$$anonymous$$g. You might want to look at some coding conventions. Why is an instance of s_EnnemyControl called "FoeHealth". And it could be null if you can't find your enemy.
Another problem in your code is line 151 of your player. You won't reach any code after a return statement. So when you're at "return closest;" the loop after won't be executed.