0

I am just getting into this whole Wrapping aspect to JsonUtility and I am having a slight issue. When I am looking at my RewardItem they always seem to be empty. Here are my classes.

[Serializable]
public class QuestData {

    public int ID;
    public string Name;
    public int MinimumLevel;
    public int[] QuestsNeeded;
    public string Description;
    public string ShortDescription;
    public string WaitingDialogue;
    public string FinishedDialogue;
    public int Experience;
    // The Items received from the quest.
    public RewardItem ChooseItemData;
    public RewardItem RewardItemData;
    public string QuestType;
    public KillType QuestKillCount;
    public TalkType QuestTalk;
    public bool Retired;

    /// <summary>
    /// Quest Data for a Kill Quest.
    /// </summary>
    public QuestData (int id, string questName, int minlevel, string questsNeeded, string description, string shortDescription, string waitingDialogue, string finishedDialogue, 
        int experience, string rewardItemIDs, string rewardItemAmounts, string chooseItemIDs, string chooseItemAmounts, string questType, string killNames, string killAmounts, 
        string talkNpcNames, string talkSceneNames, bool isRetired) {

        this.ID = id;
        this.Name = questName;
        this.MinimumLevel = minlevel;
        this.QuestsNeeded = Array.ConvertAll(questsNeeded.Split(','), int.Parse);
        this.Description = description;
        this.ShortDescription = shortDescription;
        this.WaitingDialogue = waitingDialogue;
        this.FinishedDialogue = finishedDialogue;
        this.Experience = experience;
        this.QuestType = questType;
        this.Retired = isRetired;

        // IF we dont have an empty string letting us know we want to give rewards this way,
        // ELSE we have an empty string so we make a empty RewardItem.
        if (!String.IsNullOrEmpty (rewardItemIDs)) {
            this.RewardItemData = new RewardItem (Array.ConvertAll (rewardItemIDs.Split (','), int.Parse), Array.ConvertAll (rewardItemAmounts.Split (','), int.Parse));
        } else {
            this.RewardItemData = new RewardItem ();
        }

        // IF we dont have an empty string letting us know we want to give rewards this way,
        // ELSE we have an empty string so we make a empty Choose Reward Item.
        if (!String.IsNullOrEmpty (chooseItemIDs)) {
            this.ChooseItemData = new RewardItem (Array.ConvertAll (chooseItemIDs.Split (','), int.Parse), Array.ConvertAll (chooseItemAmounts.Split (','), int.Parse));
        } else {
            this.ChooseItemData = new RewardItem ();
        }

        // IF we dont have an empty string letting us know we have a Kill Quest,
        // ELSE no kill quest.
        if (!String.IsNullOrEmpty (killNames)) {
            this.QuestKillCount = new KillType (killNames.Split (','), new int[killNames.Split(',').Length], Array.ConvertAll(killAmounts.Split(','), int.Parse));
        } else {
            this.QuestKillCount = new KillType ();
        }

        // IF we dont have an empty string letting us know we have a Talk Quest,
        // ELSE no talk quest.
        if (!String.IsNullOrEmpty (talkNpcNames)) {
            this.QuestTalk = new TalkType (talkNpcNames.Split (','), talkSceneNames.Split (','));
        } else {
            this.QuestTalk = new TalkType ();
        }
    }
}

This Quest_List code here is what I put into a JsonUtility method and then save to PlayerPrefs.

[Serializable]
public class Quest_List {
    // The Lists of quests that fall into the Accepted section.
    public List<QuestData> questAccepted = new List<QuestData> ();
    public List<QuestData> questReadyToTurnIn = new List<QuestData> ();
    public List<QuestData> questCompleted = new List<QuestData> ();
    // The Lists of quests that fall into the Not Accepted section.
    public List<QuestData> questAcceptable = new List<QuestData> ();
    public List<QuestData> questSoon = new List<QuestData> ();
    public List<QuestData> questTooHigh = new List<QuestData> ();
}

My class I use for my rewards.

[Serializable]
public class RewardItem {

    private int[] rewardItemIDs;
    private int[] rewardItemAmounts;

    public RewardItem (int[] itemID, int[] itemAmount) {
        this.rewardItemIDs = itemID;
        this.rewardItemAmounts = itemAmount;
    }

    public RewardItem () {
        this.rewardItemIDs = new int[0];
        this.rewardItemAmounts = new int[0];
    }

    public int[] GetItemIDs () {
        return this.rewardItemIDs;
    }

    public int[] GetItemAmounts () {
        return this.rewardItemAmounts;
    }
}

The wrapper that I use currently :

    public static class JsonHelper {

    public static string ToJson<T> (T items) {

        Wrapper<T> wrapper = new Wrapper<T>();
        wrapper.Items = items;
        return JsonUtility.ToJson(wrapper, true);
    }

    [Serializable]
    private class Wrapper<T> {

        public T Items;
    }
}

How I initialize my DB.

private void ConstructQuestDatabase (int level) {
    // Loop the amount of quest we have.
    for (int i = 0; i < questJsonData.Count; i++) {
        // Add to our Quest Data.
        questDatabase.Add (new QuestData (
            QuestDataInt (i, "id"),
            QuestDataString (i, "name"), 
            QuestDataInt (i, "minimumlevel"),
            QuestDataString (i, "questsneeded"),
            QuestDataString (i, "description"),
            QuestDataString (i, "shortdescription"),
            QuestDataString (i, "waitingdialogue"),
            QuestDataString (i, "finishdialogue"),
            QuestDataInt (i, "experience"),
            QuestDataString (i, "ChooseItemData"),
            QuestDataString (i, "RewardItemData"),
            QuestDataString (i, "questtype"),
            QuestDataString (i, "killtype", "name"),
            QuestDataString (i, "killtype", "amount"),
            QuestDataString (i, "talktype", "npcname"),
            QuestDataString (i, "talktype", "scenename"),
            QuestDataBool (i, "retired")
        ));
    }
}

And now the method/code in which I use the above classes :

public void Save () {               
    Quest_List questContainer = new Quest_List ();
    questContainer.questAccepted = questAccepted;
    questContainer.questReadyToTurnIn = questReadyToTurnIn;
    questContainer.questCompleted = questCompleted;
    string questToJson = JsonHelper.ToJson (questContainer);
    // Save the information.
    PlayerPrefs.SetString ("Quest_Status", questToJson);

    print (questToJson);
}

This is what I see when I print :

enter image description here

Now if we look at the QuestAccepted part you will see 4 in that image that are empty (The 2 rewards and the Kill and Talk based quests) and I know when I solve the issue for one I can apply it to the other ones but at the moment I just cannot figure out how to get that part to not be empty.

JoeyL
  • 1,295
  • 7
  • 28
  • 50
  • This is really a bad way of asking question. You did not show how that class is initiated and what values the variables contain. The empty parts are the result of empty initialization. Create a simple instance of `Quest_List`, initialize and populate the variables manually then try to serialize it to json. If the problem happens, EDIT your question with the initializing code and the json(no screenshot). – Programmer Feb 16 '18 at 01:43
  • @Programmer edited. Second to last screenshot shows you the where I create a Quest_List instance and added another screenshot to how I fill my Quest_Data. – JoeyL Feb 16 '18 at 01:45
  • @Programmer editting a screenshot as I goofed when editting it. – JoeyL Feb 16 '18 at 01:56
  • @Programmer Alright I finished editting to how it was. I ended up saying screw the RewardItems and just turn them into 2 int[]'s so I can stop wasting time on this project. But I will always welcome how to fix that issue for a future project – JoeyL Feb 16 '18 at 01:58
  • I want to help but `QuestDataString` is not anywhere in your code. If you write something no one can use to replicate your issue then you're out of luck. Also you json is still a screenshot. Move along if you find another way to this – Programmer Feb 16 '18 at 02:07
  • @Programmer Trust me you don't need to worry about those. They work as when you look at the last screenshot those are getting filled except for classes I made such as RewardItem, TalkType and KillType. The RewardItems were just strings broken into an int[] as you can see from the Array.ConvertAll (). I am almost positive it is a Wrapper issue but I am not sure how to do a wrapper inside of a wrapper. I wrapped the outside to get that to work but I feel I need another Wrapper for the inside RewardItem classes etc. – JoeyL Feb 16 '18 at 02:09
  • @Programmer If this would help in explaining it more I fixed my issue but I had to change a few things. The RewardItem, KillType and TalkType I just removed those and replaced where they were in QuestData with the primitives they had in their classes. – JoeyL Feb 16 '18 at 02:19

1 Answers1

2

Your two variables:

private int[] rewardItemIDs;
private int[] rewardItemAmounts;

are returning null because they are declared as private. Unity cannot serialize private properties unless you add a special attribute to them.

You have two options:

1.Make variables public

public int[] rewardItemIDs;
public int[] rewardItemAmounts;

2.Keep them as private but add [SerializeField] attribute to each private variable. Note that this is different than the [Serializable] that is added above classes/structs/enums.

[SerializeField]
private int[] rewardItemIDs;
[SerializeField]
private int[] rewardItemAmounts;

This should also apply to your 2 other variables with the-same issue but since they are not posted, I can't tell if they are the-same issue.

See 4.TROUBLESHOOTING JsonUtility: from my other post which shows reasons why you might be getting empty values when using JsonUtility. I will also update that post to include what's in this answer too.

Programmer
  • 121,791
  • 22
  • 236
  • 328