Unity - display Json array from server - c#

I'm making a quiz game and I'm stuck at this problem that is probably easy to do.
I have this script, which gets JSON data from server and separates it:
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System;
using TMPro;
[Serializable]
public class RootObject
{
public Results[] Result;
}
[Serializable]
public class Results
{
public string id;
public string question;
public string answer1;
public string answer2;
public string answer3;
public string answer4c;
}
public class DataLoader : MonoBehaviour
{
public PickPlace pickplace;
public string URLBase;
public void GetQustion()
{
URLBase = pickplace.url;
StartCoroutine(Run());
}
IEnumerator Run()
{
var req = CreateReturnPlayerDataRequest();
yield return req.SendWebRequest();
var results = HandleReturnPlayerDataRequest(req);
// Izvada konsolē saņemtos datus
Debug.Log("Quesiton: " + results.Result[0].question + " Answer1: " + results.Result[0].answer1 + " Answer2: " + results.Result[0].answer2 + " Answer3: " + results.Result[0].answer3 + " Answer4: " + results.Result[0].answer4c);
}
public UnityWebRequest CreateReturnPlayerDataRequest()
{
var req = UnityWebRequest.Get(URLBase);
return req;
}
public static RootObject HandleReturnPlayerDataRequest(UnityWebRequest req)
{
if (req.isNetworkError)
{
Debug.LogError("Failed to POST /player/register");
return new RootObject();
}
var results = JsonUtility.FromJson<RootObject>("{\"Result\":" + req.downloadHandler.text + "}");
return results;
}
}
My question is:
How can I call out array in, for example my GameManager script and call out separated data, so that I can put for example question text from JSON data into Text object and all 4 answers to buttons?

Currently you have a method to start the request but you never wait until / will know when it is done!
I would simply use an Action<RootObject> as parameter so you can add a callback listener and react to the result when it is invoked.
public class DataLoader : MonoBehaviour
{
public PickPlace pickplace;
public string URLBase;
public void GetQuestions(Action<RootObject> onSuccess)
{
URLBase = pickplace.url;
StartCoroutine(Run(onSuccess));
}
IEnumerator Run(Action<RootObject> onSuccess)
{
var req = CreateReturnPlayerDataRequest();
yield return req.SendWebRequest();
var results = HandleReturnPlayerDataRequest(req);
if(results == null)
{
yield break;
}
Debug.Log("Quesiton: " + results.Result[0].question + " Answer1: " + results.Result[0].answer1 + " Answer2: " + results.Result[0].answer2 + " Answer3: " + results.Result[0].answer3 + " Answer4: " + results.Result[0].answer4c);
// Now invoke the Callback so whoever started the post call gets the results
onSuccess?.Invoke(results);
}
public UnityWebRequest CreateReturnPlayerDataRequest()
{
var req = UnityWebRequest.Get(URLBase);
return req;
}
private RootObject HandleReturnPlayerDataRequest(UnityWebRequest req)
{
if(req.isHttpError || req.isNetworkError)
{
Debug.LogError($"Failed to POST /player/register! Failed with {req.responseCode} - Reason: {req.error}");
onDone?.Invoke(null);
return null;
}
var results = JsonUtility.FromJson<RootObject>("{\"Result\":" + req.downloadHandler.text + "}");
return results;
}
}
So now you can call it from another class like e.g.
// Drag these in via the Inspector
[SerializeField] private DataLoader dataLoader;
[Space]
[SerializeField] private Text questionText;
[Space]
[SerializeField] private Text button1Text;
[SerializeField] private Text button2Text;
[SerializeField] private Text button3Text;
[SerializeField] private Text button3Text;
public void SomeMethod()
{
// Do the post call and react once the results are there either as lambda expression
dataLoader.GetQuestions(results => {
Debug.Log("Successfully received data. Will update GUI", this);
// do something with the results now e.g.
var first = results.Result[0];
questionText.text = first.question;
button1Text.text = first.answer1;
button2Text.text = first.answer2;
button3Text.text = first.answer3;
button4Text.text = first.answer4;
});
// alternatively you can do the same also using a method
dataLoader.GetQuestions(OnPostRequestFinished);
}
private void OnPostRequestFinished(RootObject results)
{
Debug.Log("Successfully received data. Will update GUI", this);
// do something with the results now e.g.
var first = results.Result[0];
questionText.text = first.question;
button1Text.text = first.answer1;
button2Text.text = first.answer2;
button3Text.text = first.answer3;
button4Text.text = first.answer4;
}

Related

Firebase google login in unity trouble - Freeze when Unity Editor plays

I'm trying to use firebase and Google linked login in a game made with Unity.
I tried the search method, but the editor freezes when I try to login in the first scene.
If I play in the editor, it doesn't progress.
When I tried in the second scene, I was logged in.
But then someone else worked. So I'm not sure about this.
What did I do wrong in the Google linked login process?
How do I debug the editor when it freeze?
I am not an English speaker. I am sorry that my English is strange.
This is the code I used. It's not much different from what I searched and found.
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.Design.Serialization;
using System.Linq;
using System.Threading.Tasks;
using Firebase;
using Firebase.Auth;
using Google;
using UnityEditor;
using UnityEngine;
using UnityEngine.Serialization;
using UnityEngine.UI;
public class GoogleSignInClass : MonoBehaviour
{
public Text infoText;
public string webClientId = "310848617796-nf5a9ds97humnn8nqv5gihmnnqg6j3g4.apps.googleusercontent.com";
private FirebaseAuth auth;
private GoogleSignInConfiguration configuration;
[SerializeField] private bool IsEditor = false;
[FormerlySerializedAs("Canvas")] [SerializeField] private GameStart Canvas;
private void Awake()
{
configuration = new GoogleSignInConfiguration { WebClientId = webClientId, RequestEmail = true, RequestIdToken = true };
CheckFirebaseDependencies();
if (Application.isEditor)
IsEditor = true;
}
private void CheckFirebaseDependencies()
{
FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task =>
{
if (task.IsCompleted)
{
if (task.Result == DependencyStatus.Available)
auth = FirebaseAuth.DefaultInstance;
else
AddToInformation("Could not resolve all Firebase dependencies: " + task.Result.ToString());
}
else
{
AddToInformation("Dependency check was not completed. Error : " + task.Exception.Message);
}
});
}
public void SignInWithGoogle() { OnSignIn(); }
public void SignOutFromGoogle() { OnSignOut(); }
private void OnSignIn()
{
if (!IsEditor)
{
GoogleSignIn.Configuration = configuration;
GoogleSignIn.Configuration.UseGameSignIn = false;
GoogleSignIn.Configuration.RequestIdToken = true;
AddToInformation("Calling SignIn");
GoogleSignIn.DefaultInstance.SignIn().ContinueWith(OnAuthenticationFinished);
}
else
{
Canvas.GoMainMenu();
}
}
private void OnSignOut()
{
AddToInformation("Calling SignOut");
GoogleSignIn.DefaultInstance.SignOut();
}
public void OnDisconnect()
{
AddToInformation("Calling Disconnect");
GoogleSignIn.DefaultInstance.Disconnect();
}
internal void OnAuthenticationFinished(Task<GoogleSignInUser> task)
{
if (task.IsFaulted)
{
using (IEnumerator<Exception> enumerator = task.Exception.InnerExceptions.GetEnumerator())
{
if (enumerator.MoveNext())
{
GoogleSignIn.SignInException error = (GoogleSignIn.SignInException)enumerator.Current;
AddToInformation("Got Error: " + error.Status + " " + error.Message);
}
else
{
AddToInformation("Got Unexpected Exception?!?" + task.Exception);
}
}
}
else if (task.IsCanceled)
{
AddToInformation("Canceled");
}
else
{
AddToInformation("Welcome: " + task.Result.DisplayName + "!");
AddToInformation("Email = " + task.Result.Email);
AddToInformation("Google ID Token = " + task.Result.IdToken);
AddToInformation("Email = " + task.Result.Email);
SignInWithGoogleOnFirebase(task.Result.IdToken, task.Result.UserId);
}
}
private void SignInWithGoogleOnFirebase(string idToken, string UID) (Player.instance.setGoogleUID(UID))
{
Credential credential = GoogleAuthProvider.GetCredential(idToken, null);
auth.SignInWithCredentialAsync(credential).ContinueWith(task =>
{
AggregateException ex = task.Exception;
if (ex != null)
{
if (ex.InnerExceptions[0] is FirebaseException inner && (inner.ErrorCode != 0)) ;
AddToInformation("\nError code = " + inner.ErrorCode + " Message = " + inner.Message);
}
else
{
AddToInformation("Sign In Successful., UID: " + UID);
mainCanvas.GoInGame();
Player.instance.SetIsSignIn(true);
Player.instance.setGoogleUID(UID);
AddToInformation("Success2");
StartCoroutine(signInSetPlayer());
}
});
}
public void OnSignInSilently()
{
GoogleSignIn.Configuration = configuration;
GoogleSignIn.Configuration.UseGameSignIn = false;
GoogleSignIn.Configuration.RequestIdToken = true;
AddToInformation("Calling SignIn Silently");
GoogleSignIn.DefaultInstance.SignInSilently().ContinueWith(OnAuthenticationFinished);
}
public void OnGamesSignIn()
{
GoogleSignIn.Configuration = configuration;
GoogleSignIn.Configuration.UseGameSignIn = true;
GoogleSignIn.Configuration.RequestIdToken = false;
AddToInformation("Calling Games SignIn");
GoogleSignIn.DefaultInstance.SignIn().ContinueWith(OnAuthenticationFinished);
}
private void AddToInformation(string str) { infoText.text += "\n" + str; }

Problem by using JSON in a PHP script with Unity

I try to work inside Unity scripts with JSON datas from a SQL table. I'm using PHP to communicate with Unity.
Here is my PHP script:
<?php
try
{
$bdd = new PDO('mysql:host=xxx.mysql.db;dbname=xxx;charset=utf8', 'xxx', 'xxx');
}
catch(Exception $e)
{
die('Erreur : '.$e->getMessage());
}
$Wallet_Number = $_GET['Wallet_Number'];
$req = $bdd->prepare('SELECT Wallet_Number, NFT, Montant_Mise, Date_Spin FROM Wallets_Bets WHERE Wallet_Number = ?');
$req->execute(array($_GET['Wallet_Number']));
$req->setFetchMode(PDO::FETCH_ASSOC);
$json['Wallet_Number'] = $req->fetchAll();
$json['content'] = count($json['Wallet_Number']);
echo json_encode($json);
?>
The script is working fine, here is a result from a request:
{"Wallet_Number":[{"Wallet_Number":"XXX","NFT":"RetourFutur","Montant_Mise":"0","Date_Spin":"06\/04\/2022"},{"Wallet_Number":"XXX","NFT":"RetourFutur","Montant_Mise":"0","Date_Spin":"06\/04\/2022"},{"Wallet_Number":"XXX","NFT":"RetourFutur","Montant_Mise":"0,010000","Date_Spin":"06\/04\/2022"},{"Wallet_Number":"XXX","NFT":"RetourFutur","Montant_Mise":"0,01","Date_Spin":"06\/04\/2022"},{"Wallet_Number":"XXX","NFT":"MenInBlack","Montant_Mise":"0,01","Date_Spin":"06\/04\/2022"},{"Wallet_Number":"XXX","NFT":"Shinning","Montant_Mise":"0,10","Date_Spin":"06\/04\/2022"}],"content":6}
Here is my Unity class to manage de datas:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class OVHJsonObject
{
// Start is called before the first frame update
public string Wallet_Number;
public string NFT;
public string Montant_Mise;
public string Date_Spin;
}
And finaly the Unity script which manage the JSON datas:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using Newtonsoft.Json;
using SimpleJSON;
namespace AllArt.Solana.Example
{
public class NGetJSONData : MonoBehaviour
{
string queryURL = "https://xxx.fr/CheckWallet.php?Wallet_Number=";
public static string NPKey;
public string NValue;
public static OVHJsonObject[ ] Wallet_data = new OVHJsonObject[9] ;
void Start()
{
}
public void PopulateList() {
NPKey = SimpleWallet.instance.wallet.GetAccount(0).GetPublicKey;
Debug.Log (" NPKEY : " + NPKey);
StartCoroutine(GetRequest(queryURL + NPKey));
}
IEnumerator GetRequest(string uri)
{
using (UnityWebRequest webRequest = UnityWebRequest.Get(uri))
{
// Request and wait for the desired page.
yield return webRequest.SendWebRequest();
string[] pages = uri.Split('/');
int page = pages.Length - 1;
switch (webRequest.result)
{
case UnityWebRequest.Result.ConnectionError:
case UnityWebRequest.Result.DataProcessingError:
Debug.LogError(pages[page] + ": Error: " + webRequest.error);
break;
case UnityWebRequest.Result.ProtocolError:
Debug.LogError(pages[page] + ": HTTP Error: " + webRequest.error);
break;
case UnityWebRequest.Result.Success:
Debug.Log(pages[page] + ":\nReceived: " + webRequest.downloadHandler.text);
NValue = webRequest.downloadHandler.text;
Wallet_data[0] = JsonUtility.FromJson<OVHJsonObject>(NValue);
Debug.Log(" Wallet Name : "+ Wallet_data[0] .Wallet_Number);
break;
}
}
}
// Update is called once per frame
void Update()
{
}
}
}
}
When running, I get no error from Unity but the fowllowing line always send an empty value (no null but nothing inside)
Debug.Log(" Wallet Name : "+ Wallet_data[0] .Wallet_Number);
Do you know what I am missing ? It seems the JSON format from my PHP script is not recognize in my Unity script.
Thank you,
Type and json data you give to JsonUtility.FromJson (type, variable) are not compatible.
You have Wallet_Number and int in Json. Then you first have parse Wallet_Number and then reach other elements in Wallet_Number.
When I test with your json data this code worked:
[System.Serializable]
public class WalletData
{
// Start is called before the first frame update
public string Wallet_Number;
public string NFT;
public string Montant_Mise;
public string Date_Spin;
}
[System.Serializable]
public class WalletsData
{
public WalletData[] Wallet_Number;
public int content;
}
WalletsData wallets = JsonUtility.FromJson<WalletsData>(jsonData);
Debug.Log(wallets.Wallet_Number[0].Wallet_Number);

How to get rid of namespace.Classname on call of display()?

Is there a way to get rid of practise.AcademicProgram in the output when the display() is called for an object initialized by the parameterized constructor. In my code below this occurs when s2.Display(); is executed.
Below is my working code for the same:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace practise
{
public class AcademicProgram
{
//Memnber variables
private int programCode;
private string programName;
private int programCredits;
//Properties for reading and writting the values of private fields
public int ProgramCode { get => programCode; set => programCode = value; }
public string ProgramName { get => programName; set => programName = value; }
public int ProgramCredits { get => programCredits; set => programCredits = value; }
//Default Constructor
public AcademicProgram()
{
}
//Parameterized Constructor
public AcademicProgram (int programCode, string programName, int programCredits)
{
this.programCode = programCode;
this.programName = programName;
this.programCredits = programCredits;
}
public void DisplayResults()
{
Console.WriteLine("Program Code: {0}\nProgram Name: {1}\nProgram Credits: {2}\n", programCode, programName, programCredits);
Console.WriteLine();
}
}
public class Instructor
{
//Member variables
public string forename;
public string surname;
public int identificationNumber;
public AcademicProgram academicProgram;
//Default Constructor
public Instructor()
{
this.forename = string.Empty;
this.surname = string.Empty;
this.identificationNumber = 0;
this.academicProgram = null;
}
//Parameterized Constructor
public Instructor(string forename, string surname, int identificationNumber, AcademicProgram academicProgram)
{
this.forename = forename;
this.surname = surname;
this.identificationNumber = identificationNumber;
this.academicProgram = academicProgram;
}
// Member Function to display values of member variables on Console.
public void Display()
{
Console.WriteLine(this.forename + ", " + this.surname + ", " + this.identificationNumber + ", " + this.academicProgram);
Console.WriteLine();
}
//Driver function
static void Main(string[] args)
{
//Instantiating object to call non-static member method
Instructor p = new Instructor();
p.Go();
Console.ReadKey();
}
//Non-static Member function
public void Go()
{
//Instantiating object without passing any values on runtime.
Instructor s = new Instructor();
//Instantiating object of AcademicProgram class without passing any values on runtime.
AcademicProgram progName = new AcademicProgram ();
//Set the values of fields using properties
progName.ProgramCode = 8230;
progName.ProgramName = "Systems Development: Cocnepts and Analysis";
progName.ProgramCredits = 4;
// Instantiating object while providing values on runtime.
Instructor s2 = new Instructor("Eddie ", "Jessup", 2394589, progName);
//Call to display method
s.Display();
s2.Display();
progName.DisplayResults();
}
}
}
Which gives an output shown here
Aside from override ToString(), I was able to fix it by a simple fix in display() of Instructor class as below:
public void Display()
{
Console.WriteLine(this.forename + ", " + this.surname + ", " + this.identificationNumber + ", " + this.academicProgram.ProgramCode + ", " + this.academicProgram.ProgramName + ", " + this.academicProgram.ProgramCredits);
Console.WriteLine();
}

Unity json data from server returns null

I have a problem, where Json data is taken from server and then called out, but always outputs NULL. You can test code if you want to, Url is public.
This is Json data that I get from server
[{"id":"3","question":"Cik ir 4 + 4 = ?","answer1":"3","answer2":"13","answer3":"7","answer4c":"8"}]
How do I fix this, so Json data outputs correctly?
Thank you.
using System.Collections;
using System.Collections.Generic;
using System.Net.Mime;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System;
public class Code : MonoBehaviour
{
public Text first;
public const string URLBase = "http://91.200.67.104:8080/test/json.php";
[System.Serializable]
public class Results
{
public string id;
public string question;
public string answer1;
public string answer2;
public string answer3;
public string answer4c;
}
void Start()
{
StartCoroutine(Run());
}
IEnumerator Run()
{
var req = CreateReturnPlayerDataRequest();
yield return req.SendWebRequest();
var results = HandleReturnPlayerDataRequest(req);
first.text = results.id + " dasdasdas " + results.question;
}
public static UnityWebRequest CreateReturnPlayerDataRequest()
{
var req = UnityWebRequest.Get(URLBase);
return req;
}
public static Results HandleReturnPlayerDataRequest(UnityWebRequest req)
{
if (req.isNetworkError)
{
Debug.LogError("Failed to POST /player/register");
return new Results();
}
// Debug izvada datus console
Debug.Log("{\"Results\":" + req.downloadHandler.text + "}");
Results results = JsonUtility.FromJson<Results>("{\"Results\":" + req.downloadHandler.text + "}");
Debug.Log("ID:" + results.id + " ;question: " + results.question + " ; " + results.answer1);
Debug.Log(results.id);
Debug.Log(results.question);
Debug.Log(results.answer1);
return results;
}
}
Your deserialization class structure is incorrect.
Firstly, the json data you are receiving from the server is an array/collection (it is surrounded by square brackets "[ ]").
Secondly, you are placing it in the "Results" field of a parent object.
Therefore, this would be the correct structure:
[System.Serializable]
public class RootObject
{
public List<Results> Results;
}
[System.Serializable]
public class Results
{
public string id;
public string question;
public string answer1;
public string answer2;
public string answer3;
public string answer4c;
}
Usage:
var obj = JsonUtility.FromJson<RootObject>("{\"Results\":" + req.downloadHandler.text + "}");
Results serverData = obj.Results[0];

"InvalidCastException: Cannot cast from source type to destination type." when loading serialized data

I'd sincerely appreciate if you looked through some of my code as I can't seem to be able to fix it myself, and this will also hopefully help others understand serialization better.
I have four pieces of related code here, with anything seemingly irrelevant cut out. I'm trying to create a user profile in a set up where the user then chooses from a range of games to play. Only options/settings for the chosen games, in this case something to do with a fish, are saved.
The error in the title occurs in the 4th section [feel free to skip to that] which is the OptionsController.LoadOptions() function at
FishData.Store data = (FishData.Store)bf.Deserialize(fileOpt);
I have this at the top of all following sections:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
1) Profile data structure:
public class Profile { //Profile variables
public static string id;
public static string name;
public static string dob;
public static bool fishEnabled;
public static bool birdEnabled;
public static string stringTest;
[System.Serializable]
public class Store { //Profile variables
public string id;
public string name;
public string dob;
public bool fishEnabled;
public bool birdEnabled;
public string stringTest;
}
}
2) Fish data structure:
public class FishData { //static Fish variables to be used in game
public static bool sizeInc;
public static bool speedInc;
public static int level;
public static bool toxic;
public static bool handLeft;
public static bool timer;
public static int timerVal;
public static int percentReq;
public static int successReq;
public static string testStringTwo;
public static List<StatController.Session> sessions = new List<StatController.Session>();
[System.Serializable]
public class Store { //non static variable set for serialization
public bool sizeInc;
public bool speedInc;
public int level;
public bool toxic;
public bool handLeft;
public bool timer;
public int timerVal;
public int percentReq;
public int successReq;
public string testStringTwo;
public List<StatController.Session> sessions = new List<StatController.Session>();
}
}
3) The script where the data file was initially created and where there didn't seem to be problems:
public class ProfileController : MonoBehaviour {
public static string currentID;
//create ----
public InputField idField;
public InputField nameField;
public InputField dobField;
public Toggle fishToggle;
public Toggle birdToggle;
//open ------
public Button idTitleButton;
public Text nameText;
public Text dobText;
public Text testText;
public InputField numField;
void Save() { //saves new ID and declares required variables based on game choice
Debug.Log("id =" + idField.text + ", name = " + nameField.text + ", save");
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Create(Application.persistentDataPath + "/" + idField.text + ".dat");
Profile.Store data = new Profile.Store(); //sets Profile variables
currentID = idField.text;
data.id = idField.text;
data.name = nameField.text;
data.dob = dobField.text;
data.fishEnabled = fishToggle.isOn;
data.birdEnabled = birdToggle.isOn;
Profile.id = idField.text;
Profile.name = nameField.text;
Profile.dob = dobField.text;
Profile.fishEnabled = fishToggle.isOn;
Profile.birdEnabled = birdToggle.isOn;
bf.Serialize(file, data); //saves Profile variables
if (fishToggle.isOn) {
FishData.Store dataFish = new FishData.Store(); //sets default Fish variables
dataFish.sizeInc = false;
dataFish.speedInc = false;
dataFish.level = 5;
dataFish.toxic = true;
dataFish.handLeft = false;
dataFish.timer = false;
dataFish.timerVal = 240;
dataFish.percentReq = 0;
dataFish.successReq = 0;
bf.Serialize(file, dataFish); //saves default Fish variables
Debug.Log("level = " + dataFish.level);
}
file.Close(); //closes save file
idSelectField.text = idField.text; //ensures current ID is used as selected ID where needed
EnableOpenProfile(); //loads new profile
}
void Load() {
if (File.Exists(Application.persistentDataPath + "/" + idField.text + ".dat")) { //loads save file
currentID = idField.text;
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Open(Application.persistentDataPath + "/" + idField.text + ".dat", FileMode.Open);
Profile.Store data = (Profile.Store)bf.Deserialize(file);
nameField.text = data.name; //loads saved Profile details and settings
fishToggle.isOn = data.fishEnabled;
birdToggle.isOn = data.birdEnabled;
fishPlayButton.enabled = data.fishEnabled;
birdPlayButton.enabled = data.birdEnabled;
FishData.Store dataFish = (FishData.Store)bf.Deserialize(file); //loads saved Fish settings
FishData.sizeInc = dataFish.sizeInc;
FishData.speedInc = dataFish.speedInc;
FishData.toxic = dataFish.toxic;
FishData.timer = dataFish.timer;
FishData.level = dataFish.level;
FishData.timerVal = dataFish.timerVal;
FishData.percentReq = dataFish.percentReq;
FishData.successReq = dataFish.successReq;
FishData.handLeft = dataFish.handLeft;
file.Close(); //closes save file
nameText.text = "Name : " + data.name + " ID : " + data.id; //displays profile details
dobText.text = "DOB : " + data.dob;
}
else return;
}
}
4) The main script that produces the error when trying to load what was saved in the previous script:
public class OptionsController : MonoBehaviour {
public static bool handLeft = false;
public Toggle sizeIncToggle;
public Toggle speedIncToggle;
public Toggle toxicToggle;
public Toggle timerToggle;
public Toggle leftToggle;
public Toggle rightToggle;
public InputField levelField;
public InputField timerValField;
public InputField percentReqField;
public InputField successReqField;
void LoadOptions() {
if (File.Exists(Application.persistentDataPath + "/" + ProfileController.currentID + ".dat")) {
BinaryFormatter bf = new BinaryFormatter();
FileStream fileOpt = File.Open(Application.persistentDataPath + "/" + ProfileController.currentID + ".dat", FileMode.Open);
FishData.Store data = (FishData.Store)bf.Deserialize(fileOpt); //[[ERROR HERE]]
sizeIncToggle.isOn = data.sizeInc;
speedIncToggle.isOn = data.speedInc;
toxicToggle.isOn = data.toxic;
timerToggle.isOn = data.timer;
levelField.text = data.level.ToString();
timerValField.text = data.timerVal.ToString();
percentReqField.text = data.percentReq.ToString();
successReqField.text = data.successReq.ToString();
fileOpt.Close();
}
}
public void SaveOptions() {
Debug.Log("name = " + ProfileController.currentID + ", save");
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Create(Application.persistentDataPath + "/" + ProfileController.currentID + ".dat");
FishData.Store data = new FishData.Store();
data.sizeInc = FishData.sizeInc;
data.speedInc = FishData.speedInc;
data.toxic = FishData.toxic;
data.timer = FishData.timer;
data.level = FishData.level;
data.timerVal = FishData.timerVal;
data.percentReq = FishData.percentReq;
data.successReq = FishData.successReq;
data.handLeft = FishData.handLeft;
bf.Serialize(file, data);
Debug.Log("level = " + FishData.level);
file.Close();
}
}
Thank you.
To ensure you are serializing/deserializing in the correct order it is best that you create a "holding" class which contains both a Fish.Store variable and Profile.Store variable. If you serialize and deserilize in different orders you will run into issues like trying to deserialize a Fish.Store object to Profile.Store.
Try creating another class with public variables of Fish.Store and Profile.Store, like:
public class ExampleClass
{
public Fish.Store FishStore;
public Profile.Store ProfileStore;
public ExampleClass()
{
}
}
Then do:
ExampleClass example = new ExampleClass();
example.ProfileStore = data;
example.FishStore = dataFish;
//File Create stuff, etc
bf.Serialize(file, example);
//File close stuff, etc
And to deserialize:
ExampleClass e = (ExampleClass)bf.Deserialize(fileOpt);
data = e.ProfileStore;
dataFish = e.FishStore;
If you only wish to serialize/deserialize one class at a time, it is best practice to read/write to/from one file per serialized class.
Correct me if I'm wrong but it seems you first save Profile.Store
and then you save FishData.Store.
Then on the load you try to retreive the FishData.Store when the Profile.Store is first in the file.
(I'm assuming you use the load from script 4 and the save in script 3.)

Categories