Search Unity

Value in Interface function not returning value to script it's on

Discussion in 'Scripting' started by FrenchCanadianStudios, Sep 11, 2019.

  1. FrenchCanadianStudios

    FrenchCanadianStudios

    Joined:
    Aug 11, 2019
    Posts:
    3
    Hello! first time writing on the forum! I have a question and I was wondering if someone can help.

    I'm using an interface script which uses Raycast to get items with trigger colliders in my game. Now in one part, i want to return a value that is in my interface function to an variable that is in that script but it's not working.
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5.  
    6. public class _BatteryInteraction : MonoBehaviour, IInteractible //Interface script
    7. {
    8.  
    9.  
    10.     public int numBatteries = 0; //value i want updated and is read by another script
    11.  
    12.    
    13. void Update()
    14.     {
    15.         Debug.Log(numBatteries); //this debug never updates in game
    16.     }
    17.    
    18. public void Interactibles()
    19.     {
    20.         if (Input.GetButtonDown("Interact") && CompareTag("batteries"))
    21.         {
    22.             numBatteries += 1;
    23.             //Debug.Log(numBatteries); //if i turn this one on, it updates but doesn't return a value to the main variable
    24.             Destroy(gameObject);
    25.         }
    26.     }
    27. }
    So basically, when I destroy the gameobject with tag "batteries", I add 1 to numBatteries but because it's inside my interface function "Interactibles" it seems like it doesn't return a value to numBatteries outside the function. The debug in Update never updates but if I turn on the one in Interactibles, that one updates but never shoots out the value. I've made my numBattery public so the other script gets the value and I tried adding 1 in the inspector and the other script gets the value.

    hopefully this is not too confusing, I've only been doing this for a month and don't know if I'm using the right terminology.

    thanks in advance!
     
  2. WarmedxMints

    WarmedxMints

    Joined:
    Feb 6, 2017
    Posts:
    1,035
    numBatteries is a variable in your _BatteryInteraction class, it has nothing to do with the interface. So you are adding 1 to the numBatteries int within the instance of _BatteryInteraction which you are then destroying.

    Even if numBatteries was a variable from your interface, it still wouldn't be persistent which is what I guess you want. I don't think an interface does what you would like.
     
  3. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    When you put a variable inside your class, every "instance" of that class has its own variable. For instance, if I created an Enemy script with a Health variable and then made 3 Enemies, changing the Health on one Enemy wouldn't affect the other two Enemies.

    With your script, each _BatteryInteraction that you create has its own separate variable for "numBatteries". Changing the count on one of them won't affect any of the other ones.

    The fact that you have an interface doesn't affect this at all. The interface is just a promise that every object with that interface will implement certain functions.

    If you want to have a single variable that is shared across all instances of a class, you can do that by declaring the variable "static". For instance,
    public static int mySharedVariable;


    But you might think about whether you'd be better off creating a new object to represent the player's inventory and tracking the collected batteries there, instead of on the _BatteryInteraction class.
     
  4. FrenchCanadianStudios

    FrenchCanadianStudios

    Joined:
    Aug 11, 2019
    Posts:
    3
    I might have to explain this a bit more, sorry.

    For now, I don't have any type of inventory system. Basically, what I would like to happen is when I pick up the game object tagged batteries, I want to add a value of 1 on numBatteries. in my other script, i get that number to use the battery when needed. my _BatteryInteraction class is set on an empty game object right now. Ill post script below for context. If any else is needed, just ask! :)

    The script that gets the value:

    Code (CSharp):
    1. public class flashlightEnabling : MonoBehaviour
    2. {
    3.  
    4.     [...]
    5.     private int batteries;
    6.     private int batteryInContainer;
    7.     public GameObject _batteryContainer;
    8.  
    9.     [...]
    10.  
    11.     void Start()
    12.     {
    13.     [...]
    14.  
    15.         batteryInContainer = _batteryContainer.GetComponent<_BatteryInteraction>().numBatteries;
    16.         batteries = batteryInContainer;
     
  5. WarmedxMints

    WarmedxMints

    Joined:
    Feb 6, 2017
    Posts:
    1,035
    You want to increment the int in your flashlightEnabling class instance, not the batteryInteractable. You could either do that by getting a reference to flashlighEnabling in the battery class and then incrementing the int by one when a battery is collected.

    Personally, I would use a scriptable object as a middleman, increment an int on that and fire an event when it is changed. The flashlight could then listen to that event or reference the int in the SO.
     
  6. FrenchCanadianStudios

    FrenchCanadianStudios

    Joined:
    Aug 11, 2019
    Posts:
    3
    Thanks WarmedxMints. I solved the issue with what i think you said before reading your second reply lol.

    So basically, the reason why I was trying to do this in the first place is the battery variable inside flashlightEnabling wasn't getting a value when I picked up a battery before acquiring the flashing since the player flashlight was disabled, thus not getting the value.

    The problem I had here was instead of pushing the battery to flashlightEnabling script, I was trying to get flashlightEnabling to retrieve the batteries once enabled from _batteryInteraction.

    I resolved this problem by going back to my original idea but with a buffer like you mentioned.

    So, I pick up the battery and place in container script:
    Code (CSharp):
    1. public class _BatteryInteraction : MonoBehaviour, IInteractible
    2. {
    3.  
    4.     public GameObject battery;
    5.     public GameObject batteryContainer;
    6.  
    7.  
    8.     public void Interactibles()
    9.     {
    10.         if (Input.GetButtonDown("Interact"))
    11.         {
    12.             batteryContainer.GetComponent<BatteryContainer>().batteryInContainer += 1;
    13.             Destroy(battery);
    14.         }
    15.     }
    16. }
    I inventory the batteries picked up in the buffer script:

    Code (CSharp):
    1. public class BatteryContainer : MonoBehaviour
    2. {
    3.  
    4.     public int batteryInContainer;
    5.  
    6.     public void Start()
    7.     {
    8.         batteryInContainer = 0;
    9.     }
    10.  
    11. }
    And finally, I retrieve the batteries once I acquire the flashlight:
    Code (CSharp):
    1. public class flashlightEnabling : MonoBehaviour
    2. {
    3. [...]
    4.  
    5.     public GameObject _batteryContainer;
    6.  
    7. [...]
    8.  
    9.     void Start()
    10.     {
    11.     [...]
    12.  
    13.         batteries = _batteryContainer.GetComponent<BatteryContainer>().batteryInContainer;
    14.  
    15. [...]
    A little funny context: The only reason why this was essential of it to work was if by any change the player picked up a battery BEFORE the flashlight it would count it.

    Thanks for the help!!

    EDIT: I spoke too quickly lol Now, if I pick up the flashlight before and get the battery, it doesn't update...

    EDIT 2: After a bit of testing, if I add:

    Code (CSharp):
    1. player.GetComponent<flashlightEnabling>().batteries += 1;
    inside the _batteryInteraction script (inside the Interactibles part), it makes it work. I thought it would add double the amount of batteries but it doesn't... It almost seems like once the flashlight script is enabled, it does count the batteryContainer script.
     
    Last edited: Sep 11, 2019
  7. WarmedxMints

    WarmedxMints

    Joined:
    Feb 6, 2017
    Posts:
    1,035
    With the way you are doing it, you would want to reference the int in the container each time you wanted to do something. Also, rather than waste time looking for the container on the gameobject reference I expect you are assigning in the inspector, just get a reference to the class instance...

    Code (CSharp):
    1. public class BatteryContainer : MonoBehaviour
    2. {
    3.     [System.NonSerialized]
    4.     public int BatteryInContainer = 0;
    5. }
    Code (CSharp):
    1. public class Battery : MonoBehaviour, IInteractible
    2. {
    3.     public BatteryContainer batteryContainer;
    4.  
    5.     public void Interactibles()
    6.     {
    7.         if (Input.GetButtonDown("Interact"))
    8.         {
    9.             batteryContainer.BatteryInContainer++;
    10.             Destroy(gameObject);
    11.         }
    12.     }
    13. }
    Code (CSharp):
    1. public class Flashlight : MonoBehaviour
    2. {
    3.     public BatteryContainer BatteryContainer;
    4.  
    5.     //Example usage
    6.     public void TurnOn()
    7.     {
    8.         //We don't have enough batteries to use the flashlight so exit function
    9.         if (BatteryContainer.BatteryInContainer < 2)
    10.             return;
    11.  
    12.         //If the code gets this far, then we have the required amount of batteries.
    13.         //Do what we want with the flashlight.
    14.     }
    15. }
     
    FrenchCanadianStudios likes this.