I am trying to save several instances of a class in a Generic List. I am assigning game objects to the gameobject list in the inspector and grabbing the sheet script from each of them and putting those into another list that will be saved. I keep getting an “ArgumentOutOfRangeException: Argument is out of range. Parameter name: index” Error and I am not sure why.
public class CharacterManager : MonoBehaviour
{
public static CharacterManager characterManager;
void Awake () {
if (characterManager == null) {
characterManager = this;
DontDestroyOnLoad (gameObject);
}else if(characterManager != this){
Destroy(gameObject);
}
}
public List<GameObject> CharactersSaveAndLoad = new List<GameObject>(1);
private List<CharacterSheet> CharacterSheetsSaveAndLoad = new List<CharacterSheet>(1);
public void GetSheets(){
for (int i = 0; i < 10; i++) {
CharacterSheetsSaveAndLoad[i] = CharactersSaveAndLoad[i].GetComponent<CharacterSheet>();
}
}
public void Save(){
BinaryFormatter bf = new BinaryFormatter ();
FileStream file = File.Create (Application.persistentDataPath + "/playerInfo.dat");
GetSheets ();
CharacterData data = new CharacterData ();
data.Sheets = CharacterSheetsSaveAndLoad;
bf.Serialize (file, data);
file.Close();
Debug.Log ("Save Compleated");
}
public void Load(){
}
}
//[serializable]
public class CharacterData{
public List<CharacterSheet> Sheets;
}
Avoid using fixed values for the loops.
A List provides a property named ‘Count’, use that for the loops condition.
In order to fill the other List, do not use the indexer ( ) in this case, it’s better to use the Add method unless you need to re-assign some specific entries. But then you have to make sure that the list has at least n+1 entries, if you want to assign the element with index n.
I fixed it and it now saves but I have come across another problem when trying to load back to the object.
I have this in the awake method of the sheet on an object.
Assets/_Scripts/Characters/CharacterSheets/CharacterSheet.cs(45,34): error CS0120: An object reference is required to access non-static member `CharacterManager.Load(CharacterSheet)’
I think I fixed the problem but now I have an issue with serialization. when I put an object in the list of gameobject for saving, it says the character sheet is not marked as serializable. I think okay i’ll just put [System.Serializable] at the top of the script and see what happens. It then proceeds to give me another error saying that the script that the sheet inherits from isn’t marked so I put [System.Serializable] at the top of that and test it. finally it gives me the error that monobehavior is not marked. I know that if I were to somehow serialize monobehaviour I would end up with huge save files and that seems counter productive. I probably doing something wrong so some help would be appreciated.
My Revised Script:
public class CharacterManager : MonoBehaviour
{
public static CharacterManager characterManager;
void Awake () {
if (characterManager == null) {
characterManager = this;
DontDestroyOnLoad (gameObject);
}else if(characterManager != this){
Destroy(gameObject);
}
}
public List<GameObject> CharactersSaveAndLoad = new List<GameObject>(2);
private List<CharacterSheet> CharacterSheetsSaveAndLoad = new List<CharacterSheet>(2);
public void GetSheets(){
CharacterSheetsSaveAndLoad.Clear();
for (int i = 0; i < CharactersSaveAndLoad.Count; i++) {
CharacterSheetsSaveAndLoad.Add (CharactersSaveAndLoad[i].GetComponent<CharacterSheet>());
}
}
public void Save(){
BinaryFormatter bf = new BinaryFormatter ();
FileStream file = File.Create (Application.persistentDataPath + "/playerInfo.dat");
GetSheets ();
CharacterData data = new CharacterData ();
data.Sheets = CharacterSheetsSaveAndLoad;
bf.Serialize (file, data);
file.Close();
Debug.Log ("Save Compleated");
}
public static void Load(GameObject CharacterObject){
CharacterSheet objectCharacterSheet = CharacterObject.GetComponent<CharacterSheet>();
//CharacterSheet findCharacterSheet = CharacterObject.GetComponent<CharacterSheet>();
if (File.Exists (Application.persistentDataPath + "/playerInfo.dat")) {
BinaryFormatter bf = new BinaryFormatter ();
FileStream file = File.Open (Application.persistentDataPath + "/playerInfo.dat", FileMode.Open);
CharacterData data = (CharacterData)bf.Deserialize(file);
file.Close();
for (int i = 0; i < data.Sheets.Count; i++){
if (data.Sheets[i].objectID == objectCharacterSheet.objectID){
//findCharacterSheet = data.Sheets[i];
objectCharacterSheet.characterName = data.Sheets[i].characterName;//findCharacterSheet.characterName;
}
}
}
}
}
[System.Serializable]
public class CharacterData{
public List<CharacterSheet> Sheets;
}