after the lazy initialization lecture for some reason when i play a handfull of enemies get a null reference exception in the start method of Fighter.cs on the line currentweapon.ForceInit() and my weapon pickups no longer work and also get a null reference exception in the OnTriggerEnter(collider other) on the line other.GetComponent().EquipWeapon(weapon);
heres my Fighter.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
using RPG.Movement;
using RPG.Core;
using RPG.Saving;
using RPG.Attributes;
using RPG.Stats;
using GameDevTV.Utils;
using System;
namespace RPG.Combat
{
public class Fighter : MonoBehaviour, IAction, ISaveable, IModifierProvider
{
[SerializeField] float timeBetweenAttacks = 1f;
[SerializeField] Transform rightHandTransform = null;
[SerializeField] Transform leftHandTransform = null;
[SerializeField] Weapon defaultWeapon = null;
[SerializeField] string defaultWeaponName = "Unarmed";
Health target;
float timeSinceLastAttack = Mathf.Infinity;
LazyValue<Weapon> currentWeapon;
Mover movement;
void Awake()
{
LazyValue<Weapon> currentWeapon = new LazyValue<Weapon>(SetupDefaultWeapon);
movement = GetComponent<Mover>();
}
private Weapon SetupDefaultWeapon()
{
AttachWeapon(defaultWeapon);
return defaultWeapon;
}
void Start()
{
currentWeapon.ForceInit();
}
void Update()
{
timeSinceLastAttack += Time.deltaTime;
if (target == null) { return; }
if (!target.IsAlive()) { return; }
if (!GetIsInRange())
{
movement.MoveTo(target.transform.position, 1f);
}
else
{
movement.Cancel();
AttackBehavior();
}
}
public void EquipWeapon(Weapon weapon)
{
currentWeapon.value = weapon;
AttachWeapon(weapon);
}
void AttachWeapon(Weapon weapon)
{
Animator animator = GetComponent<Animator>();
weapon.Spawn(rightHandTransform, leftHandTransform, animator);
}
public Health GetTarget()
{
return target;
}
private void AttackBehavior()
{
transform.LookAt(target.transform);
if (timeSinceLastAttack >= timeBetweenAttacks)
{
// this will trigger the Hit() event in the animation
TriggerAttack();
timeSinceLastAttack = 0f;
}
}
private void TriggerAttack()
{
GetComponent<Animator>().ResetTrigger("stopAttack");
GetComponent<Animator>().SetTrigger("attack");
}
// animation event
void Hit()
{
if (target == null) { return; }
float damage = GetComponent<BaseStats>().GetStat(Stat.Damage);
if (currentWeapon.value.HasProjectile())
{
currentWeapon.value.LaunchProjectile(rightHandTransform, leftHandTransform, target, gameObject, damage);
}
else
{
target.TakeDamage(gameObject, damage);
}
}
void Shoot()
{
Hit();
}
private bool GetIsInRange()
{
return Vector3.Distance(transform.position, target.transform.position) <= currentWeapon.value.GetWeaponRange();
}
public void Attack(GameObject combatTarget)
{
GetComponent<ActionScheduler>().StartAction(this);
target = combatTarget.GetComponent<Health>();
}
public bool CanAttack(GameObject combatTarget)
{
if (combatTarget == null) { return false; }
Health targetToTest = combatTarget.GetComponent<Health>();
return targetToTest != null && targetToTest.IsAlive();
}
public void Cancel()
{
StopAttack();
target = null;
movement.Cancel();
}
private void StopAttack()
{
GetComponent<Animator>().ResetTrigger("attack");
GetComponent<Animator>().SetTrigger("stopAttack");
}
public IEnumerable<float> GetAdditiveModifiers(Stat stat)
{
if (stat == Stat.Damage)
{
yield return currentWeapon.value.GetWeaponDamage();
}
}
public IEnumerable<float> GetPercentageModifiers(Stat stat)
{
if (stat == Stat.Damage)
{
yield return currentWeapon.value.GetPercentageBonus();
}
}
public object CaptureState()
{
return currentWeapon.value.name;
}
public void RestoreState(object state)
{
string weaponName = (string)state;
Weapon weapon = Resources.Load<Weapon>(weaponName);
EquipWeapon(weapon);
}
}
}
and heres my WeaponPickup.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace RPG.Combat
{
public class WeaponPickup : MonoBehaviour
{
[SerializeField] Weapon weapon = null;
[SerializeField] float respawnTime = 5f;
void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("Player"))
{
other.GetComponent<Fighter>().EquipWeapon(weapon);
StartCoroutine(HideForSeconds(respawnTime));
}
}
IEnumerator HideForSeconds(float seconds)
{
ShowPickup(false);
yield return new WaitForSeconds(seconds);
ShowPickup(true);
}
private void ShowPickup(bool shouldShow)
{
gameObject.GetComponent<BoxCollider>().enabled = shouldShow;
foreach (Transform child in transform)
{
child.gameObject.SetActive(shouldShow);
}
}
}
}