I have a pretty "basic" combat class here. It has a Player and an Enemy. They are inherrited from a Character class and have values such as health, armor and ar (attack rating (damage)). I am trying to set the combat up in a way so that once you press a button (in this case, e), you attack the enemy and the enemy attacks you. I think this is most easily done by having a method in Update() which constantly checks whether or not my desired key is pushed, and if it is, to execute said method which has 2 attacks. I have rearranged the program so that the Player and Enemy are saved seperately in the methods "savePlayer" and "saveEnemy".
Relevant global objects:
public Player Player;
public EnemyCharacterCreator Enemy;
public Player savedPlayer;
public EnemyCharacterCreator savedEnemy;
public Text[] savedArray;
My constructor:
public Combat(Player Player, EnemyCharacterCreator Enemy, Text[] texxtArray)
{
savePlayer(Player);
saveEnemy(Enemy);
saveTextArray(texxtArray);
textChanges();
// FightLoop();
}
Aforementioned methods:
public void savePlayer(Player Player)
{
savedPlayer = Player;
}
public void saveEnemy(EnemyCharacterCreator Enemy)
{
savedEnemy = Enemy;
}
Combat-related code:
public void attackButton()
{
if (Input.GetKeyDown("e") == true)
{
FightLoop();
}
}
public void FightLoop()
{
PlayerAttack();
EnemyAttack();
textChanges();
}
public void PlayerAttack()
{
savedEnemy.health = savedEnemy.health - savedPlayer.ar;
}
public void EnemyAttack()
{
savedPlayer.health = savedPlayer.health - savedEnemy.ar;
}
Conceptually this should work fine, except it doesn't. When I "manually" execute FightLoop() in the constructor (commented out in the first code block) it works and the enemies health is reduced by 45 (which is my players' ar value), yet when I put attackButton() into the Update() function I get a NullReferenceException whenever I press e. 1 The error leads to line 74, which is the only line within the PlayerAttack() method:
savedEnemy.health = savedEnemy.health - savedPlayer.ar;
I put a breakpoint there and the savedEnemy object was null. I have no idea why, it is a global object and it works perfectly when I do it "manually", without Update(). Help would be appreciated.
A Minimal Complete Verifiable Example as requested in the comments:
There are 4 Scripts.
Combat:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Combat : MonoBehaviour
{
bool playerTurn = true;
bool invActive = false;
public Player Player;
public Enemy Enemy;
public Text[] textArray = new Text[6];
public Player savedPlayer;
public Enemy savedEnemy;
public Text[] savedArray;
public Combat(Player Player, Enemy Enemy, Text[] textArrayPass)
{
savePlayer(Player);
saveEnemy(Enemy);
saveTextArray(textArrayPass);
//textChanges();
// FightLoop();
textChanges();
}
public void saveTextArray(Text[] textArray)
{
savedArray = new Text[6];
savedArray = textArray;
//Debug.Log(savedArray[0].text);
}
public void savePlayer(Player Player)
{
savedPlayer = Player;
}
public void saveEnemy(Enemy Enemy)
{
savedEnemy = Enemy;
}
public void attackButton()
{
if (Input.GetKeyDown("e") == true)
{
Debug.Log(Player.health);
FightLoop();
Debug.Log(Player.health);
}
}
public void FightLoop()
{
PlayerAttack();
EnemyAttack();
textChanges();
}
public void PlayerAttack()
{
savedEnemy.health = savedEnemy.health - savedPlayer.ar;
}
public void EnemyAttack()
{
savedPlayer.health = savedPlayer.health - savedEnemy.ar;
}
public void textChanges()
{
savedArray[0].text = savedPlayer.health.ToString();
savedArray[1].text = savedPlayer.armor.ToString();
savedArray[2].text = savedPlayer.ar.ToString();
savedArray[3].text = savedEnemy.health.ToString();
savedArray[4].text = savedEnemy.armor.ToString();
savedArray[5].text = savedEnemy.ar.ToString();
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
attackButton();
}
private void Awake()
{
Combat fight = new Combat(Player, Enemy, textArray);
}
}
Character:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Inventory
{
public int[] inventory;
public Inventory(int inventorySlots)
{
inventory = new int[inventorySlots];
Debug.Log("Your Inventory has " + inventorySlots + " slots.");
}
}
public class Character : MonoBehaviour
{
public Inventory charInventory;
public int health = 125;
public int armor = 10;
public int cash = 100;
public int ar = 45;
public bool weaponEquipped;
public Character()
{
Inventory charInventory = new Inventory(20);
}
//HaheaghehAEH
public void attack(Character enemy)
{
int oldHealth = enemy.health;
enemy.health = enemy.health - ar;
int damage = oldHealth - enemy.health;
Debug.Log(damage + " damage!");
}
public Character returnChar()
{
Character x = new Character();
return x;
}
}
Player:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : Character
{
public Player()
{
health = 150;
ar = 45;
}
}
Enemy:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy : Character
{
public Enemy()
{
health = 87;
ar = 15;
Inventory enemyInventory = new Inventory(5);
}
}


MonoBehaviourinstances withnew- Unity should be throwing warnings for you about that. Did you perhaps mean to useAddComponentto attach a new instance of aMonoBehaviourcomponent, orGetComponentto get a reference to an existing one? \$\endgroup\$