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

Problem passing data

Discussion in 'Scripting' started by taskmagee, Oct 18, 2021.

  1. taskmagee

    taskmagee

    Joined:
    Sep 16, 2018
    Posts:
    31
    I have a class that stores all the data pertinent to a unit for an army. One of those pieces of data is an array that stores all the upgrades the unit has.

    Code (CSharp):
    1. public class CustomAssembledUnit
    2. {
    3.     public UnitData unitData;
    4.     //Array I'm having issues with
    5.     public UpgradeCard[] upgradeCards;
    6.     public int totalPoints;
    7.     public GameObject unitButton;
    8.     public GameObject categoryButton;
    9.     public GameObject activatedUnitButton;
    10.     public TextMeshProUGUI categoryText;
    11. }
    When the class is create and all the data is assigned, it's stored in another script to be called at a later time.

    Code (CSharp):
    1.  
    2.  
    3. private CustomAssembledUnit unitData;
    4.  
    5. public void InitializeButton(CustomAssembledUnit storedUnit)
    6.     {
    7.         unitData = storedUnit;
    8.     }
    If I run a Debug.Log on the unitData variable everything is fine and all the data is there. The problem is when I call that data at a later point.

    Code (CSharp):
    1. public void OnPointerClick(PointerEventData eventData)
    2.     {
    3.         CustomAssembledUnit unit = cancelButton.ReturnUnitData();
    4.  
    5.         Debug.Log(unit.unitData.unitName);
    6.         Debug.Log(unit.totalPoints);
    7.         Debug.Log(unit.upgradeCards.Length + " upgrade cards");
    8.         for (int i = 0; i < unit.upgradeCards.Length; i++)
    9.         {
    10.             Debug.Log(unit.upgradeCards[i]);
    11.         }
    12.     }
    13.  
    14. public CustomAssembledUnit ReturnUnitData()
    15.     {
    16.         return unitData;
    17.     }
    When I run a Debug.Log on the upgrades after returning it, every index shows a null result. What would be the reason that specific piece of data isn't being passed back?
     
  2. RadRedPanda

    RadRedPanda

    Joined:
    May 9, 2018
    Posts:
    1,596
    Don't think it's possible for anyone to figure out the problem with these snippets of code, or at least I couldn't. What is cancelButton? What did your other Debugs return? Where's your code actually setting the upgradeCards in the first place?

    A few things you could try:
    • Try right-clicking upgradeCards and clicking "Find All References" (might be called something else in other IDEs, but I use Visual Studio). This will show you every place that you reference the upgradeCards, be it setting or getting. You can print before and after every place you set the value, to make sure it's actually getting set.
    • Attach a debugger to your code and run through it line by line, while watching the value. This will guarantee you find your problem, but I've had problems getting it to work consistently with Unity.
    • Just give more code so we can identify the problem area.
     
    Bunny83 likes this.
  3. taskmagee

    taskmagee

    Joined:
    Sep 16, 2018
    Posts:
    31
    Using your recommendations, I was able to locate the issue. Thank you for your response.
     
  4. taskmagee

    taskmagee

    Joined:
    Sep 16, 2018
    Posts:
    31
    So I've tracked down the issue but now I can't make sense of why the array is being cleared. I've removed a bunch of code because it's all UI related and don't want it cluttering the post.

    Code (CSharp):
    1. public class ActivatedButton : MonoBehaviour, IPointerClickHandler
    2. {
    3.     private CustomAssembledUnit unitData = new CustomAssembledUnit();
    4.  
    5.     public void InitializeButton(CustomAssembledUnit storedUnit)
    6.     {
    7.         unitData = storedUnit;
    8.         UnitCustomization uc = GameObject.FindObjectOfType<UnitCustomization>();
    9.         uc.CancelButton();
    10.     }
    11. }
    So basically what happens, the player creates a unit for an army and that unit data is sent to this button script that stores it in case the player wants to edit it and then the script that was handling the customizing has its variables and ui elements cleared through the CancelButton and ResetButton functions.

    Code (CSharp):
    1.  
    2. private UpgradeCard[] upgrades;
    3.  
    4. public void CancelButton()
    5. {
    6.         ResetButton();
    7. }
    8.  
    9. public void ResetButton()
    10. {
    11.         for (int x = 0; x < upgrades.Length; x++)
    12.         {
    13.             upgrades[x] = null;
    14.         }
    15. }
    This for loop is the problem. I've commented out the line that calls the CancelButton funtion and the data was stored as expected and then I commented out just the for loop and again worked as expected. So I know for sure that loop is the issue. It clears the upgrades in the customization script but when I do that it also clears the upgrades in the button script. This is what I don't understand. If I basically copy the storedUnit data into the unitData variable and then clear the original storedUnit, why is it clearing the unitData variable. As I understand it, that shouldn't be affected. If you need to see all the code I can upload it to a shared folder on google drive.
     
    Last edited: Oct 18, 2021
  5. RadRedPanda

    RadRedPanda

    Joined:
    May 9, 2018
    Posts:
    1,596
    So almost all objects are "passed by reference by value", which sounds confusing, but basically, you can just assume everything acts as if it is passed by reference. That means unitData is not a copy of storedUnit, it is storedUnit. What you're going to want to do is initialize a new CustomAssembledUnit and copy the data over.
     
  6. taskmagee

    taskmagee

    Joined:
    Sep 16, 2018
    Posts:
    31
    Confusing is right. I thought I did exactly that which obviously I didn't because it isn't working. But didn't I initialize a new CustomAssembledUnit in line 3

    Code (CSharp):
    1. private CustomAssembledUnit unitData = new CustomAssembledUnit();
    and then copy it in line 7

    Code (CSharp):
    1. unitData = storedUnit;
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,947
    In your first post above, third block of code, you make a local variable
    unit


    Do you ever assign that to
    unitData
    , which you return in the getter?
     
  8. taskmagee

    taskmagee

    Joined:
    Sep 16, 2018
    Posts:
    31
    It is assigned unless I'm not understanding what you're saying. It's like RedRedPanda stated being a reference issue. It's not actually copying the data. Because if it changes on the original it also changes it on the new but if I don't change anything and run a debug on the new unit all the data is there.
     
  9. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,947
    All I'm sayin' is that
    unit
    is a local variable that never goes anywhere...

    all_im_sayin.png

    Perhaps that's not what you intend anyway. Just seems odd to make a local and do nothing with it.
     
  10. taskmagee

    taskmagee

    Joined:
    Sep 16, 2018
    Posts:
    31
    Oh I see what you're saying. I shouldn't have included that bottom portion. That's for a something separate. The code is a mess right now. I need to clean it up