I cannot get my Health Potion to work in Unity - c#

I am creating a health potion for my game, however, it does not seem to work. My "if" statement does not seem to be getting called but if I get rid of the "if" statement a null reference appears. I am not sure what to do.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HealthPotion : MonoBehaviour
{
public int heal = 25;
[Header("Input")]
public KeyCode healKey = KeyCode.Alpha1;
void Update()
{
if (Input.GetKeyDown(healKey)) Heal();
}
void Heal()
{
PlayerHealth currentHealth = GetComponent<PlayerHealth>();
if (currentHealth != null)
{
currentHealth.AddHealth(heal);
Debug.Log("Heal");
}
Destroy(gameObject);
}
}
Here is my Player Health code (which does not get called because of the problem occurring in my Health Potion code).
public void AddHealth(int heal)
{
currentHealth = currentHealth =+ heal;
healthbar.SetCurrentHealth(currentHealth);
if(currentHealth >= maxHealth)
{
currentHealth = maxHealth;
}
Debug.Log("Healed");
}

Related

Visual studio can't find definition for TakeDamage from another method

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.

How can I make a public "enemyDamage" integer from 1 script, communicate with another script?

I am new to coding and am not quite sure how to add context from 1 script to another. For my game so far, I have been Frankensteining code from multiple sources and have head into a dead end. I want my player to take the same amount of damage as stated by enemyDamage in the 'Enemy' script. I'm not too sure what other context to give you, but if you know how you could help me out, that would be awesome!
Enemy Script
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using UnityEngine;
public class Enemy : MonoBehaviour
{
public int health = 100;
public int enemyDamage = 10;
public GameObject deathEffect;
public void TakeDamage (int damage)
{
health -= damage;
if (health <= 0)
{
Die();
}
}
void Die ()
{
Instantiate(deathEffect, transform.position, Quaternion.identity);
Destroy(gameObject);
}
}
PlayerHealth Script
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using UnityEngine;
public class PlayerHealth : MonoBehaviour
{
public int maxHealth = 10;
public int currentHealth;
public int damage = 1;
public HealthBar healthBar;
// Start is called before the first frame update
void Start()
{
currentHealth = maxHealth;
healthBar.SetMaxHealth(maxHealth);
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.R))
{
TakenDamage(1);
}
if (currentHealth <= 0)
{
PlayerDeath();
}
}
public void TakenDamage(int damage)
{
currentHealth -= damage;
healthBar.SetHealth(currentHealth);
}
void PlayerDeath()
{
UnityEngine.Debug.Log("bean guy");
}
public void OnTriggerEnter2D(Collider2D hitInfo)
{
UnityEngine.Debug.Log("We did it boys");
PlayerHealth player = hitInfo.GetComponent<PlayerHealth>();
{
UnityEngine.Debug.Log("beans");
TakenDamage(enemyDamage); // I need this to update with enemyDamage 's value
}
}
}
There are multiple ways:
Make EnemyDamage a Static Variable
public static int enemyDamage = 10;
Then you can call it in other scripts with Enemy.enemyDamage
Be aware that you can't set static variables in the Inspector.
Use GetComponent
Enemy enemy = gameObject.GetComponent(typeof(Enemy )) as Enemy;
enemy.enemyDamage
Create a GameManager
GameManager.CS:
#region Singelton
public static GameManager instance;
void Awake()
{
if (instance != null)
{
Debug.LogWarning("More than one Instance of Inventory found");
return;
}
instance = this;
}
#endregion
public int enemyDamage = 10;
Referencing the GameManager Script:
GameManager gm;
void Start()
{
gm = GameManager.instance;
}
//Calling Function in GameManager
gm.EndGame();
// Getting Value from GameManager
gm.enemyDamage();
When to use what?
If you want a more short term solution I would use a static variable, not advised with multiple enemies (different enemyDamage Values are now immosible)
If you have more variables or even functions that need to be accessible from multiple scripts I would advise you to use a Game Manager instead
You need to get a reference of the Enemy to use GetComponent, but makes it possible to add multiple different enemyDamage Values

Unity 2D, C# - Why my OnCollisionEnter2D doesn't collide?

So, i created two scripts, one named "Stats.cs" registers the player stats and the other one named "PlayerHealth.cs" "makes" the player take damage on contact and updates the Hearts in the HUD. My problem is, whenever i collide with an object that has a tag named "Projectile" it simply doesn't work, my player doesn't take damage at all. The Stats.cs script isn't in any object, the PlayerHealth.cs is in my Player object.
Stats.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class Stats{
private int health;
public int maxHP = 3;
public int Health
{
get
{
//Some code
return health;
}
set
{
//Some code
health = Mathf.Clamp(value, 0, maxHP);
}
}
public void SetHealth()
{
Health = maxHP;
}
}
PlayerHealth.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PlayerHealth : MonoBehaviour
{
Stats playerStats = new Stats();
public int curHealth;
public int numOfHearts = 3;
public Image[] hearts;
public Sprite fullHeart;
public Sprite emptyHeart;
void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.CompareTag("Projectile"))
{
Debug.Log("Hello");
DamagePlayer(1);
Destroy(other.gameObject);
}
}
public void DamagePlayer(int damage)
{
playerStats.Health -= damage;
}
// Start is called before the first frame update
void Start()
{
playerStats.SetHealth();
curHealth = numOfHearts;
}
// Update is called once per frame
void Update()
{
curHealth = playerStats.Health;
numOfHearts = playerStats.maxHP;
if (curHealth>numOfHearts){
curHealth = numOfHearts;
}
if(curHealth <= 0){
Die();
}
for (int i = 0; i < hearts.Length; i++)
{
if(i < curHealth){
hearts[i].sprite = fullHeart;
} else
{
hearts[i].sprite = emptyHeart;
}
if(i < numOfHearts){
hearts[i].enabled = true;
} else {
hearts[i].enabled = false;
}
}
}
void Die(){
//Restart
Application.LoadLevel(Application.loadedLevel);
}
}
curHealth is updating so it will stay as the actual Health in Stats and will change the images in HUD.
The Player has a RigidBody2D on him two colliders, one is a box for the body, and the other is a circle collider, so when the player crouches, the circle collider disables.
The Projectiles also have and RigidBody2D with 0 gravity (so it won't fall in mid air) and a BoxCollider2D.
I would check and make sure that the projectile is tagged as Projectile and that the BoxCollider doesn't have "Is Trigger" checked.
I should also say, iterating with that for loop in the Update is very bad practice performance wise. That is happening literally as fast as the machine can loop it and it is doing that every time. I would look into updating it on an event.
Hope this helps!

Healthbar not decreasing when player is collided with the laser

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

Identifier Expected error on 2D Collision Code?

I am trying to make a oncollision2D EnemyDamage is done removing health from playerStats.health, unfortunately I got the error, "Identifier expected" does anyone know what I need to put there to get the code to work? Thanks error on Collision (8,41).
Collision damage code:
using UnityEngine;
using System.Collections;
public class Collision : MonoBehaviour {
int EnemyDamage = 1;
void OnCollisionEnter2D(Collision2D)
{
playerStats.Health -= EnemyDamage;
}
}
Player Health Code:
using UnityEngine;
using System.Collections;
public class Player : MonoBehaviour {
[System.Serializable]
public class PlayerStats {
public int Health = 100;
}
public PlayerStats playerStats = new PlayerStats();
public int fallBoundary = -20;
void Update () {
if (transform.position.y <= fallBoundary)
DamagePlayer (9999999);
}
public void DamagePlayer (int damage) {
playerStats.Health -= damage;
if (playerStats.Health <= 0) {
GameMaster.KillPlayer(this);
}
}
}
Collision2D is a class and is used to return collision information when used with the OnCollisionEnter2D callback function. If you are going to use it, you have to put a variable after it.
void OnCollisionEnter2D(Collision2D)
{
}
should be
void OnCollisionEnter2D(Collision2D col)
{
playerStats.Health -= EnemyDamage;
}
If you don't need to get information about the collison, you can just use the OnCollisionEnter2D function without Collision2D parameter at-all.
void OnCollisionEnter2D()
{
playerStats.Health -= EnemyDamage;
}

Categories

Resources