Variables not being updated with get and set [SOLVED]
So i have a very weird problem happening here. Basically i have a boolean variable that is private (and has always been private so it was never serialized) that i am i trying to set in a different script and the set function gets called every time i want it to be however when i look at the variable in the Update function of my script it never changes.
using UnityEngine;
using System.Collections;
namespace MedievalMayhem.Weapons {
[RequireComponent(typeof(BoxCollider))]
public class MeleeWeapon : Weapon
{
private BoxCollider _hitZone;
private bool _hitZoneOn = true;
public bool HitZoneOn {
get{
Debug.Log ("Getting hitZoneOn " + this._hitZoneOn);
return _hitZoneOn;
}
set{
Debug.Log ("Setting hitZoneOn " + value);
this._hitZoneOn = value;
}
}
protected override void Start() { // edit 2 changed to protected override void
base.Start ();
Debug.Log ("Setting hitzone");
this._hitZone = GetComponent<BoxCollider> ();
this._hitZone.enabled = this._hitZoneOn;
}
void Update() { //edit 2 removed public
Debug.Log ("Hit zone is: " + this._hitZone.enabled);
Debug.Log ("Setting hitzone enabled to " + HitZoneOn);
this._hitZone.enabled = HitZoneOn;
}
void OnTriggerEnter(Collider hit) { //edit 2 removed public
Debug.Log ("HIT " + hit.tag);
}
}
}
The above is the class that is causing the problem. When I run this I will see something like the following in my editor console:
As you can see from the above output the HitZoneOn:set
function is called 597 times just like the rest of the calls but is split between setting the variable to true
and setting it to false
, however, the HitZoneOn:get
function never returns false. Also if i initially set the _hitZoneOn
to false
instead of true
it will always get false
even though it is set to true
at times.
It is probably worth mentioning that I originally tried to use other functions such as:
public void TurnHitZoneOn() {
this._hitZone.enabled = true;
}
public function TurnHitZoneOff() {
this._hitZone.enabled = false;
}
however with the above code the _hitZone
variable is always null outside of the Start
and Update
functions. It is as if I can't access and modify any variables outside of my Start
and Update
functions. I do this is various other scripts and I have tried to restart unity and change the variable names and no matter what i do i can't seem to set any of my variables in this script.
Any ideas as to what is going on here would be greatly appreciated!
Thanks
EDIT:
using UnityEngine;
using System.Collections;
using MedievalMayhem.Weapons;
namespace MedievalMayhem.Entities {
public class PlayerFighting {
[SerializeField] private GameObject weapon;
void Start() {
//starting stuff
}
void Update() {
this.weapon.GetComponent<MeleeWeapon>().HitZoneOn = Input.GetButton("Attack");
}
}
}
EDIT 2: Weapon Script
using UnityEngine;
using System.Collections;
namespace MedievalMayhem.Weapons {
public class Weapon : MonoBehaviour {
[SerializeField] private int _damage;
[SerializeField] private GameObject _dropPrefab;
private bool _droppable;
protected virtual void Start() {
if (this._dropPrefab != null) {
this._droppable = true;
} else {
this._droppable = false;
}
}
public bool IsDroppable() {
return this._droppable;
}
public GameObject GetDropPrefab() {
return this._dropPrefab;
}
}
}
EDIT 3
So I have changed my MeleeWeapon script to be the following:
using UnityEngine;
using System.Collections;
namespace MedievalMayhem.Weapons {
[RequireComponent(typeof(BoxCollider))]
public class MeleeWeapon: Weapon
{
public BoxCollider hitZone;
void Awake() {
hitZone = this.GetComponent<BoxCollider> ();
if (hitZone == null) {
Debug.LogError ("NO BOX COLLIDER");
}
}
void OnTriggerEnter(Collider hit) {
Debug.Log ("HIT " + hit.tag);
}
}
}
and I have changed the line to enable the collider in the PlayerFighting script to the following:
//check if the weapons should be enabled or disabeled
bool input = Input.GetButton("Fire1");
this._right_hand_weapon.GetComponent<WeaponMelee>().hitZone.enabled = input;
and I now get the following error whenever I try to access the hitZone variable:
UnassignedReferenceException: The variable hitZone of WeaponMelee has not been assigned.
You probably need to assign the hitZone variable of the WeaponMelee script in the inspector.
MedievalMayhem.Player.PlayerFighting.Update () (at Assets/Scripts/Entities/PlayerFighting.cs:70)
(PlayerFighting.cs:70 refers to the above line)
I don't under stand what is going on. I never get the error that says 'NO BOX COLLIDER' so It shouldn't be null but for some reason in other scripts it is.
Maybe it is worth mentioning that this object is a runtime instantiated object using the following:
private GameObject AddGear(GameObject prefab, GameObject parent) {
GameObject child = (GameObject)Instantiate (
prefab,
prefab.transform.position,
prefab.transform.rotation
);
child.transform.parent = parent.transform;
child.transform.localPosition = prefab.transform.position;
child.transform.localRotation = prefab.transform.rotation;
child.transform.localScale = prefab.transform.localScale;
return child;
}
//this is called in the PlayerFighting script
this._right_hand_weapon = this.AddGear (pickUp.GetPrefab (), this._right_hand_weapon_hold);
Just because I have no idea what to do or say and I am rambling on the entire code base im using can be found on my github at: https://github.com/Tyler-Gauch/MedievalMayhem maybe theres something in the scipts that im failing to mention?
Thanks again for all your help
I have updated my answer. I was unsure if it mattered seeing how even components that are set inside the Start()
function are null in all other functions except Update*()
functions.
I think the problem with your "false all the time" is using GetButton. It returns false as long as the button is not held down and called in update. Holding the button down should give you a constant true.
Then I noticed, you're deriving from a Weapon class, which might be important to see.
Then, there's the three Unity events Start, Update and OnTriggerEnter, all public. Those are usually private.
For using Start and Update properly make them "protected virtual void" in the Weapon class and "protected override void" in $$anonymous$$eleeWeapon. If Weapon does not do anything in any of those two, they don't even need to exist and can just be added as ordinary void in $$anonymous$$eleeWeapon. Otherwise, your Update is missing the base call.
Answer by tag104367 · Nov 01, 2016 at 03:26 AM
So I have figured out the issue! The issue had nothing to do with my WeaponMelee class and everything to do with Instantiating of the weapon itself. I was using the following function to instantiate an object:
private GameObject AddGear(GameObject prefab, GameObject parent) {
GameObject child = Instantiate (
prefab,
prefab.transform.position,
prefab.transform.rotation
) as GameObject;
child.transform.parent = parent.transform;
child.transform.localPosition = prefab.transform.position;
child.transform.localRotation = prefab.transform.rotation;
child.transform.localScale = prefab.transform.localScale;
return child;
}
I also have the ability to give the PlayerFighting script a starting right hand weapon that is accessible in the inspector. Say I gave the inspector the Axe prefab (Named Axe). I was then doing this in my Start function for the PlayerFighting script:
public void Start() {
if (this._right_hand_weapon != null) {
this._hasWeapon = true;
if (this._right_hand_weapon_hold.transform.childCount == 0) {
this.AddGear (this._right_hand_weapon, this._right_hand_weapon_hold);
}
}
}
What happened was the _right_hand_weapon was still equal to the original Axe prefab because I forgot the set the AddGear's return to my _right_hand_weapon. So by changing the second code snippet to the following:
public void Start() {
if (this._right_hand_weapon != null) {
this._hasWeapon = true;
if (this._right_hand_weapon_hold.transform.childCount == 0) {
this._right_hand_weapon = this.AddGear (this._right_hand_weapon, this._right_hand_weapon_hold);
}
}
}
my problem was fixed because I was referencing the new instantiated object not the old prefab from the inspector
I apologize to those attempting to help me as I didn't provide all the needed information. Learned my lesson on this one that more information is better! Thank you to both of you for helping you pushed me in the right direction!
Answer by ElijahShadbolt · Nov 01, 2016 at 12:38 AM
With just the scripts you have shared, it seems to be working perfectly. When you hold the mouse down, the Box Collider is enabled, and when it is not held down, it is disabled. Maybe the problem is in the TurnHitZoneOn/Off functions. When you try to set _hitZone.enabled directly, it is immediately replaced by the MeleeWeapon's _hitZoneOn value in the next frame. Instead of setting _hitZone.enabled = true/false;
, you should set HitZoneOn = true/false;
so that it will be updated next frame.
I overhauled all of your scripts in the way I saw fit, just in case.
Weapon.cs
using UnityEngine;
namespace $$anonymous$$edieval$$anonymous$$ayhem.Weapons {
public class Weapon : $$anonymous$$onoBehaviour {
[SerializeField]
private int _damage;
[SerializeField]
private GameObject _dropPrefab;
public GameObject dropPrefab { get { return _dropPrefab; } } // same as the GetDropPrefab() function
private bool _droppable;
public bool isDroppable { get { return _droppable; } } // same as the IsDroppable() function
protected virtual void Awake() {
_droppable = _dropPrefab; // same as _droppable = (_dropPrefab != null);
}
}
}
$$anonymous$$eleeWeapon.cs
using UnityEngine;
namespace $$anonymous$$edieval$$anonymous$$ayhem.Weapons {
[RequireComponent(typeof(BoxCollider))]
public class $$anonymous$$eleeWeapon : Weapon {
private BoxCollider _hitZone;
private bool _hitZoneOn = true;
public bool HitZoneOn {
get {
return _hitZoneOn;
}
set {
_hitZoneOn = value;
UpdateHitZoneOn();
}
}
private void UpdateHitZoneOn() {
_hitZone.enabled = _hitZoneOn;
}
protected override void Awake() {
base.Awake();
_hitZone = GetComponent<BoxCollider>(); // finding _hitZone
UpdateHitZoneOn(); // initializing _hitZone.enabled
}
void Update() {
UpdateHitZoneOn(); // updating _hitZone.enabled
// this means setting the box collider's .enabled field in a different script has no effect;
// you can only change _hitZone.enabled via this script's HitZoneOn property
Debug.Log("_hitZone.enabled is now " + _hitZone.enabled);
}
void OnTriggerEnter(Collider hit) {
Debug.Log("HIT " + hit.tag);
}
}
}
PlayerFighting.cs
using UnityEngine;
using $$anonymous$$edieval$$anonymous$$ayhem.Weapons;
namespace $$anonymous$$edieval$$anonymous$$ayhem.Entities {
public class PlayerFighting : $$anonymous$$onoBehaviour {
[SerializeField]
private GameObject weapon;
void Start() {
// starting stuff
}
void Update() {
if (weapon && weapon.GetComponent<$$anonymous$$eleeWeapon>()) // check that the weapon is not null
weapon.GetComponent<$$anonymous$$eleeWeapon>().HitZoneOn = Input.GetButton("Attack");
}
}
}
Thank you for the reply however its still not working :(
$$anonymous$$aybe i'm having some weird bug in unity where it butchered my script in some config file when creating the script? If it is working for you that's all i can think of. I am going to try and just delete the script and recreate it and see what happens.
Also when adding the UpdateHitZoneOn() function to the HitZoneOn:set function i get the following error:
UnassignedReferenceException: The variable _hitZone of Weapon$$anonymous$$elee has not been assigned. You probably need to assign the _hitZone variable of the Weapon$$anonymous$$elee script in the inspector.
Although inside the Update loop the _hitZone variable is set.
Tried recreating the script with different names and such and still no luck :(
Also just created an entirely new project and I get the same problem
Your answer
![](https://koobas.hobune.stream/wayback/20220612095724im_/https://answers.unity.com/themes/thub/images/avi.jpg)