- Home /
Strange inheritance behaviour (Two different values)
Hello, I'm currently programming a weapon system with automatic, semi auto, melee and throwable weapons. It is built up using inheritance (see UML diagram). I made a overriden Update loop that increases the fireRateCounter in the AutomaticWeapon class. But when I call Fire() from the Player it doesn't work. But when I call it from AutomaticWeapon's Update or Start it works.
I really dont understand that problem, a solution would be awsome. Thanks you.
https://answers.unity.com/storage/temp/150743-uml.png
using UnityEngine;
public abstract class Weapon : MonoBehaviour {
public abstract void Fire();
public abstract void Update();
}
public class AutomaticWeapon : Weapon {
public float fireRate = .2f;
public float fireRateCounter;
public override void Fire() {
Debug.Log(fireRateCounter); //INCORRECT OUTPUT; Why is it 0???
if (fireRateCounter >= fireRate) {
Debug.Log("FIRE()");
}
}
public override void Update() {
fireRateCounter += Time.deltaTime;
Debug.Log(fireRateCounter); //CORRECT OUTPUT; Why is it correct here?
}
}
using UnityEngine;
public class Player : MonoBehaviour {
public Weapon weapon;
private void Update() {
if (Input.GetMouseButton(0)) {
weapon.Fire();
}
}
}
I'm not 100% sure what is causing the inconsistency you're seeing, but you do not need to abstract and override the Update
method in components. Unity calls it, and the other $$anonymous$$onoBehaviour
callbacks via reflection. The override may be causing unexpected/unintuitive things to happen under the hood.
In the script AutomaticWeapon
,fireRateCounter
never increases when you call the method Fire()
from player. $$anonymous$$aybe you can try something like this.
public override void Fire() {
Debug.Log(fireRateCounter);
if (fireRateCounter >= fireRate) {
fireRateCounter -= fireRate;
Debug.Log("FIRE()");
}else{
fireRateCounter += Time.deltaTime;
//Logic for when the weapon is still in cooldown
}
}
As suggested by @$$anonymous$$ishotta, it's better to avoid implementing Update
method via abstract. As long as your class inherit from $$anonymous$$onobehaviour
, you have access to this method from within the class.
Answer by Bunny83 · Jan 03, 2020 at 11:51 AM
I can't see any error in the provided code. I would simply assume that this "weapon" variable does not point to the correct object in the scene but rather to a prefab in the project. This is a common mistake and can easily be tested by adding a context object to the Debug.Log statements as second parameter. This way the Unity editor will "ping" / highlight this object whenever you click on the log message in the console. This makes it easier to figure out what object did actually produce this log message.
Also you should always use meaningful and unique log messages so you do not confuse them.
// use this in Update
Debug.Log("AutomaticWeapon::Update current fire rate counter = " + fireRateCounter, gameObject);
// use this in Fire
Debug.Log("AutomaticWeapon::Fire current fire rate counter = " + fireRateCounter, gameObject);
Thank you so much, the weapon variable really points towards the prefab, because this script is faulty. Furthermore I will keep your advices in $$anonymous$$d.
private void StartWeapon(Transform spawnWeapon) {
Transform newWeapon = Instantiate(spawnWeapon, transform.GetChild(0));
newWeapon.name = spawnWeapon.name;
weapon = **spawnWeapon**.GetComponentInChildren<AutomaticWeapon>();
}
Your answer
Follow this Question
Related Questions
Component Class Hierarchy 2 Answers
Help with using JsonUtility.FromJsonOverwrite 1 Answer
Using functions of Inherited classes 3 Answers