Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Script Values Resetting to 0

Discussion in 'Scripting' started by sieks-, Oct 28, 2019.

  1. sieks-

    sieks-

    Joined:
    Aug 29, 2019
    Posts:
    17
    Hello,
    I am new to Unity and still determining best practices.

    I have a character which can hold two Gun objects. Gun is an abstract class from which other classes like AssaultRifle and Pistol inherit from. These two classes set values for things like firerate, number of bullets, etc.
    On my character, I have a weaponslot which can hold two Gun objects (in my script I have two public Gun objects), and in the inspector, I have added the assault rifle and pistol.

    When I try to update the GUI with the values from the primary weapon slot, which is holding an assault rifle, it knows that there is an assault rifle there, but the values are resetting to 0 rather than what is set their respective classes.

    Does anyone know what my issue might be? I can provide more information if necessary. Additionally, if my procedure for this type of game system is not best practice, can anyone provide a description for the best way to accomplish what I wish to achieve?

    Thanks.
     
  2. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    14,446
    Please share your code, the behavior you expect and what you are actually seeing, and the results of your debugging
     
  3. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,835
    What do you mean by "what is set [in] their respective classes?"

    My silver-bullet guess is that you are wondering what happened to the values you set in the constructor, and that the answer is that they are being overridden by the values saved in Unity's inspector.

    Other answers are possible. For instance, maybe the objects have all the right values but your UI code is bugged so that it always prints zeroes regardless of the input data.

    If you need more help, you should provide technical details of where the "correct" values are supposed to be coming from and how they get from there to your UI. You may also want to narrow down the exact point in that chain when the values first differ from what you expect (e.g. using Debug.Log statements).
     
  4. sieks-

    sieks-

    Joined:
    Aug 29, 2019
    Posts:
    17
    Thank you for the quick replies - I will provide my code and pictures later tonight when I'm on my main computer.

    @Antistone I think your guess may be on the right track. The googling I did led me to a similar conclusion as well. As I mentioned, I will post my code later, but as an example

    Code (CSharp):
    1. protected int MagSize;
    is a field within the Gun abstract class. This is the way I would design it outside of Unity. Then within the AssaultRifle class, I fill in the values in Awake (e.g. MagSize = 30).
    I see that removing the fields from Gun and moving them to AssaultRifle (and having them either private or protected) allows the fields to retain their values, however this essentially ruins the need for the abstract class. I know I have a misunderstanding somewhere in how the values are stored/passed between what I see in the inspector and what is set at runtime.

    As I mentioned, I will post the code later tonight if I'm still clear as mud.
     
  5. sieks-

    sieks-

    Joined:
    Aug 29, 2019
    Posts:
    17
    I know in the pictures that there are some compiler errors due to protection levels - this is when I was messing around with them in order to test what values were stored, due to things I read online.
    Basically from this, I want to know how to keep the Gun class abstract and allow it to function the way it is intended, namely: accessing AssaultRifle values from the primary weapon slot.

    Please let me know if something is still not obvious.
     

    Attached Files:

  6. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,835
    Please post code using code tags, not screenshots. As JeffD said, it would also be a good idea to provide your actual test output.

    Are the weapons assigned to your player prefab assets, or are they actual objects instantiated in your scene? (One of them has "prefab" in the object name.) Unity magic methods like Awake aren't going to be called on prefabs because they aren't actually present in your game.
     
    sieks- and SparrowGS like this.
  7. Stardog

    Stardog

    Joined:
    Jun 28, 2010
    Posts:
    1,890
    The post above seems to be the answer.

    If you are prototyping, you can probably just drag the Assault_Rifle/etc prefabs into the scene, then drag them into the primary/secondary slots from there. MonoBehavours instantiate when they are on a GameObject that exists in the scene.
     
  8. sieks-

    sieks-

    Joined:
    Aug 29, 2019
    Posts:
    17
    The weapons are not instantiated in the scene. There only 'reference' to the scene is within that last picture; from being placed in the primary/secondary slots in the inspector.
     
  9. sieks-

    sieks-

    Joined:
    Aug 29, 2019
    Posts:
    17
    Yes I believe this is the source of the error. So you mean just literally drag them somewhere onto the scene, effectively instantiating them that way? I guess this would be a good method for testing, but in the long run I'm looking for something more 'hidden'. I feel like instantiating/destroying each time the player changes a weapon seems kind of like overkill, but in reality, I don't know Unity well at all so I don't know if this is a good path forward.
     
  10. Stardog

    Stardog

    Joined:
    Jun 28, 2010
    Posts:
    1,890
    If you don't want them in the scene it can be a regular C# class (non-monobehaviour) or a ScriptableObject. You would store them in an item/weapons database. Then read the data from there. It depends on your game.

    For a doom style game, you can just have all the guns on the player, but they are disabled, and just SetActive them when they are "picked up" and "selected". For a more open game with large inventories and equipable items it will be a little bit more complicated.
     
    sieks- likes this.
  11. sieks-

    sieks-

    Joined:
    Aug 29, 2019
    Posts:
    17
    -- Ahh of course, I may tweak things and just put all the weapon stats within a non-Monobehaviour class. Maybe a traditional, non-Unity singleton to avoid setting the same information more than once.
    I tried ScriptableObjects too, but I ran into the same problem (I guess I wasn't using it properly).

    -- And since this is my first game, I don't want to make things too complicated. I am thinking of letting the user select the primary and secondary weapons from a menu screen and then start playing (no changes in weapons once the game starts).

    Thanks to everyone for answering!
     
  12. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,835
    The point of prefabs is to act like a blueprint for you to stamp out copies of an object. If you only want one copy, prefabs are probably a poor choice.

    Regarding putting one copy of a prefab in your scene so that it runs: note that the copy in your scene will be distinct from the prefab itself, and so you will need to change all your references to point to the copy in your scene and not the original prefab. The prefab itself will still never Awake.

    Scriptable objects and plain C# classes aren't going to Awake, either--you'll have to initialize them in some other way. For scriptable objects, that way is probably just editing their public fields in Unity's inspector. For plain C#, you can use constructors or other traditional C# methods.