I have added the following script to my enemies for the purpose of having a health bar:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Enemy_Health : MonoBehaviour {
public float health;
public float maxHealth;
public GameObject healthBarUI;
public Slider slider;
private void Start()
{
health = maxHealth;
slider.value = calculateHealth();
}
private void Update()
{
slider.value = calculateHealth();
if (health < maxHealth)
{
healthBarUI.SetActive(true);
}
if (health <= 0)
{
Destroy(gameObject);
}
if (health > maxHealth)
{
health = maxHealth;
}
}
float calculateHealth()
{
return health / maxHealth;
}
}
It is working well. However, my player has a weapon (axe) and I would like when my player attacks using the weapon, the health bar of the enemy decreases.
Add a function that decreases the health of enemy on attack. Something like this:
public void DecreaseHealth(healthamount)
{
health -= healthamount;
}
Call this function in your player script with the exact health you want to decrease on attack.
Related
I am making health and damage script in Unity.
I have error CS0117 'PlayerHealth' does not contain a definition for 'TakeDamage'
I want player to have 20 healths and when touched an object it will damage him.
I tried searching on google but I didn't find answer.
PlayerHealth script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour
{
public int health = 20;
public void TakeDamage(int damage)
{
health -= damage;
if (health <= 0)
{
Destroy(gameObject, 0.3f);
}
}
}
And for EnemyDamage script I use this code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerHealth : MonoBehaviour
{
public int DMG;
float cooldown = 0f;
private void Update()
{
Debug.Log(cooldown);
cooldown -= Time.deltaTime;
}
private void OnCollisionEnter(Collision collision)
{
PlayerHealth health = collision.gameObject.GetComponent<PlayerHealth>();
if (cooldown <= 0)
{
if (health != null)
{
PlayerHealth.TakeDamage(DMG);//here is the error
}
cooldown = 1f;
}
}
}
PlayerHealth.TakeDamage(DMG); tries to call a static method TakeDamage on the class PlayerHealth but there is no such method, hence the error.
Your code is a little mess anyway, lets clean it up.
Attach this script to your game objects which can lose health (e.g. a player):
public class Health : MonoBehaviour // you called it NewBehaviourScript
{
public int health = 20;
public void TakeDamage(int damage) {
health -= damage;
if (health <= 0) {
Destroy(gameObject, 0.3f);
}
}
}
Attach this script to your game objects which can inflict damage:
public class Damage : MonoBehaviour // you called it PlayerHealth (?!)
{
public int DMG;
float cooldown = 0f;
void Update()
{
Debug.Log(cooldown);
cooldown -= Time.deltaTime;
}
void OnCollisionEnter(Collision collision)
{
if (cooldown <= 0f) {
Health health = collision.gameObject.GetComponent<Health>();
if (health != null) {
// call TakeDamage on the collided >instance<
health.TakeDamage(DMG);
}
cooldown = 1f;
}
}
}
This should give you a starting point with an appropriate colliders setup.
I'm new to Unity and together with a few friends, I try to make a game. I was trying to connect the healthbar I made to the damage u can deal by shooting knifes. First to test this I used:
void Update()
{
if (Input.GetKeyDown(KeyCode.Mouse1))
{
TakeDamage(25);
}
}
Everything worked fine and when I pressed Mouse1 the healthbar worked.My goal was, that when a knife hits the enemy 25 damage is dealt and the healthbar shows that the enemy lost health. However, when the knifes hit the enemy nothing happens. Can you please help me because I tried fixing this for like 3 hours and I'm getting kinda frustrated. Thank you.
Here's the code for the healthbar:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class healthbar : MonoBehaviour
{
public Slider slider;
public void SetMaxHealth(int health)
{
slider.maxValue = health;
slider.value = health;
}
public void SetHealth(int health)
{
slider.value = health;
}
}
And here's the code for the enemy:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy_Follow : MonoBehaviour
{
public float speed;
public Transform target;
public int damage = 25;
public int maxHealth = 100;
public int currentHealth;
public healthbar healthBar;
// Start is called before the first frame update
void Start()
{
currentHealth = maxHealth;
healthBar.SetMaxHealth(maxHealth);
target = GameObject.FindGameObjectWithTag("Player").GetComponent<Transform>();
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Mouse1))
{
TakeDamage(25);
}
transform.position = Vector2.MoveTowards(transform.position, target.position, speed * Time.deltaTime);
}
public void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Knife")
{
TakeDamage(25);
}
}
public void TakeDamage(int damage)
{
currentHealth -= damage;
healthBar.SetHealth(currentHealth);
}
}
After finding out that your colliders are not triggers it should rather be OnCollisionEnter2D like e.g.
public void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Knife"))
{
TakeDamage(25);
}
}
See also Colliders -> Collision Action Matrix
You may try this code to look if the slider works at all. If this code does work (You can change things with the inspector) then it should be an error with the collision/trigger detection and nothing else.
public class SliderTest : MonoBehaviour {
public Slider slider;
public int maxHealth = 100;
private int currentHealth = 100;
public bool resetHealth = false;
public bool damage = false;
void Start() {
slider = GetComponent<Slider>();
SetMaxHealth(maxHealth);
}
void Update() {
if(resetHealth) {
resetHealth = false;
SetHealth(maxHealth);
}
if(damage) {
damage = false;
SetHealth(currentHealth-10);
}
}
public void SetMaxHealth(int health) {
slider.maxValue = health;
slider.value = 100;
}
public void SetHealth(int health) {
currentHealth = health;
slider.value = currentHealth;
}
}
}
I am trying to decrease the healthbar of the player whenever he collides with an enemy laser but the script that I wrote is not working and it is giving me the following error:
Assets/Scripts/Laser/HealthManager.cs(19,21): error CS0029: Cannot implicitly convert type void' to UnityEngine.UI.Slider.
Can someone take some time and review my code and tell me why the healthbar is not working? Thank you.
HealthManager script :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class HealthManager : MonoBehaviour {
public int CurrentHealth { get; set; }
public int MaxHealth { get; set; }
public Slider HealthBar;
//public GameObject LaserBulletEnemyPreFab;
//public GameObject PlayerPrefab;
//public LaserLevelManager myLevelmanager;
// Use this for initialization
void Start () {
MaxHealth = 20;
CurrentHealth = MaxHealth; //Resseting the health on start
HealthBar = CalculatingHealth();
}
// Update is called once per frame
void Update()
{
if(GetComponent<Collider>().gameObject.tag == "EnemyLaser")
{
Destroy(GetComponent<Collider>().gameObject);
DealDamage(1);
}
}
void DealDamage(int DamageValue)
{
CurrentHealth -= DamageValue; //Deduct the damage dealt from the player's health
HealthBar = CalculatingHealth();
if(CurrentHealth <= 0) //If health is 0
{
PlayerDead(); //Calling the function
}
}
void CalculatingHealth()
{
int healthdecrease = CurrentHealth / MaxHealth;
}
void PlayerDead()
{
CurrentHealth = 0; //Currenthealth is 0
LaserLevelManager.LoadLevel("Lose"); //Take player to the lose scene
}
}
HealthBar is of type Slider. CalculatingHealth is a function that does not return anything (so void).
You try to set a variable initialy initialized to type Slider to a void value. This is not possible.
You could:
float CalculatingHealth()
{
return healthdecrease = CurrentHealth / MaxHealth;
}
And
HealthBar.value = CalculatingHealth();
Note: https://docs.unity3d.com/ScriptReference/UI.Slider-value.html
I want the player to take damage whenever the enemy is near, the enemy will take damage but the player doesn't(i tried taking away the function that kills the enemy to check if it is too quick). I am quite new to unity and this is one of my first "independent" scripts, so it may be a quite obvious error. There are no errors or warnings however.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AttackableScript : MonoBehaviour {
public float health;
public float attackSpeed;
public float damage;
public float radious = 3f;
public Transform enemyArea;
bool dead = false;
public GameObject player;
public float KillCount;
public void Die()
{
Debug.Log(health);
health = health - 0.04f;
if (health == 0f)
{
dead = true;
}
}
IEnumerator Attack()
{
GameObject thePlayer = GameObject.Find("player");
PlayerMovement playerScript = thePlayer.GetComponent<PlayerMovement>();
playerScript.playerHealth = playerScript.playerHealth - damage;
yield return new WaitForSeconds(attackSpeed);
Debug.Log("player health = " + playerScript.playerHealth);
}
void Update() {
float distance = Vector3.Distance(player.transform.position, enemyArea.position);
if (distance <= radious && dead != true)
{
Attack();
}
if (health <= 0)
{
health = 0;
Destroy(gameObject);
Destroy(this);
}
}
}
the game is 2d.
I asked a discord and they pointed out my misuse of coroutines, i forgot to start one when i called the attack function. So instead of Attack() , it was StartCoroutine(Attack());
im having a problem from my enemyDamage script in unity5 when i play it and stick to the enemy i died instantly even the enemy damage is 10 and my health was 100
well this is my first time to make this things on unity hope you helps me :(
heres my code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class enemydmg : MonoBehaviour {
public float damage;
public float damagerate;
public float pushbackforce;
float nextdamage;
bool playerInRange = false;
GameObject theplayer;
playerHealth theplayerhealth;
// Use this for initialization
void Start () {
nextdamage = Time.time;
theplayer = GameObject.FindGameObjectWithTag ("Player");
theplayerhealth = theplayer.GetComponent<playerHealth> ();
}
// Update is called once per frame
void Update () {
if (playerInRange)
Attack ();
}
void OnTriggerEnter (Collider other)
{
if (other.tag == "Player")
{
playerInRange = true;
}
}
void OnTriggerExit (Collider other)
{
if (other.tag == "Player")
{
playerInRange = false;
}
}
void Attack()
{
if (nextdamage <= Time.time)
{
theplayerhealth.addDamage(damage);
nextdamage = Time.time + damagerate;
pushback (theplayer.transform);
}
}
void pushback(Transform pushObject)
{
Vector3 pushDirection = new Vector3 (0, (pushObject.position.y - transform.position.y), 0).normalized;
pushDirection *= pushbackforce;
Rigidbody pushedRB = pushObject.GetComponent<Rigidbody> ();
pushedRB.velocity = Vector3.zero;
pushedRB.AddForce (pushDirection, ForceMode.Impulse);
}
}
and this was my playerhealth
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class playerHealth : MonoBehaviour {
public float fullhealth;
float currentHealth;
// Use this for initialization
void Start () {
currentHealth = fullhealth;
}
// Update is called once per frame
void Update () {
}
public void addDamage(float damage)
{
currentHealth -= damage;
if (currentHealth <= 0) {
makeDead ();
}
}
public void makeDead()
{
Destroy (gameObject);
}
}
theplayerhealth = theplayer.GetComponent<playerHealth> ();
I think this line of code fails you because the player is a GameObject. theplayerhealth is or should already be initialized in your other script. I think you could approach polymorphism in a better way.
public class enemydmg : playerHealth{
}
This will allow you to directly inherit everything you need from the playerHealth script without having to grab extra components. You can also use this technique for may other scripts in the future.
Another approach that you could use is calling your class directly:
playerHealth.addDamage(damage);
From now on when you name your scripts use capitalization. PlayerHealth, EnemyDamage, etc... That's just a pro-tip to make your code look a bit cleaner when you're doing things like this. (Optional)