我有这个List<GameObject> character;
包含我想在游戏中随机生成的所有角色的数据。在最初的游戏中,我们只有一个数据,即列表中的一个GameObject。当我从商店购买角色时,它们会被添加到这个名为"角色"的列表中。所有这些现在都运行良好。问题是,当我在购买角色后退出游戏并再次播放时,这些购买并未被保存。我想知道一种保存和加载list<GameObject> characters
的方法。我尝试了PlayerPrefs
,但它似乎不执行lists
的保存,这是我知道如何统一保存的唯一方法。任何帮助与代码。我已经看到字符串分隔符(如果我发音正确的话)可以完成这项工作。但我不知道它会做什么,怎么做,有人能帮助我吗?谢谢。
更新问题 这是我的商店脚本代码:
[System.Serializable] public class ShopItem
{
public Sprite CharacterImage;
public GameObject charactersModel;
public int Price;
public bool isPurchased = false;
}
public List<ShopItem> ShopItemsList;
[Header("Panel Holders")]
[SerializeField] GameObject MainMenu;
[SerializeField] GameObject SettingsHolder;
[SerializeField] GameObject ShopPanel;
[Space]
[Header("Item Template & Display")]
GameObject ItemTemplate;
GameObject g;
[SerializeField] Transform ShopScrollView;
Button buyBtn;
//String Delimiter for Characters is "/"
public char mCharacterDemiliter = '/';
GameObject getGameManager;
GameManager GameManagerRef;
public string mPurchasedCharaters = string.Empty;
public string[] mPurchasesCharacterList;
private void Start()
{
getGameManager = GameObject.Find("GameManager");
GameManagerRef = getGameManager.GetComponent<GameManager>();
ItemTemplate = ShopScrollView.GetChild(0).gameObject;
var length = ShopItemsList.Count;
for (int i = 0; i < length; i++)
{
g = Instantiate(ItemTemplate, ShopScrollView);
g.transform.GetChild(0).GetComponent<Image>().sprite = ShopItemsList[i].CharacterImage;
g.transform.GetChild(1).GetComponentInChildren<TextMeshProUGUI>().text = ShopItemsList[i].Price.ToString();
buyBtn = g.transform.GetChild(2).GetComponent<Button>();
if (ShopItemsList[i].isPurchased)
{
DisableBuyButton();
}
buyBtn.AddEventListener(i, OnShopItemBtnClicked);
}
Destroy(ItemTemplate);
}
private void OnEnable()
{
//GameManagerRef.isCharacterPurchased = PlayerPrefs.GetString("SaveCharacterPurchaseData");
GameManagerRef.mPurchasedCharaters = PlayerPrefs.GetString("SavedCharacters");
mPurchasesCharacterList = mPurchasedCharaters.Split(mCharacterDemiliter);
foreach (var sub in mPurchasesCharacterList)
{
ShopItemsList[].isPurchased = true;
Debug.Log(int.Parse(sub));
DisableBuyButton();
}
}
public void DisableBuyButton()
{
buyBtn.interactable = false;
buyBtn.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = "PURCHASED";
//Destroy(buyBtn);
}
public void OpenShop()
{
MainMenu.SetActive(false);
SettingsHolder.SetActive(false);
ShopPanel.SetActive(true);
}
public void ReturnButton()
{
MainMenu.SetActive(true);
SettingsHolder.SetActive(true);
ShopPanel.SetActive(false);
}
int boolToInt(bool val)
{
if (val)
return 1;
else
return 0;
}
void OnShopItemBtnClicked(int itemIndex)
{
if (GameManagerRef.HasEnoughCoins(ShopItemsList[itemIndex].Price))
{
//purchase Item
GameManagerRef.UseCoins(ShopItemsList[itemIndex].Price);
ShopItemsList[itemIndex].isPurchased = true;
buyBtn = ShopScrollView.GetChild(itemIndex).GetChild(2).GetComponent<Button>();
GameManagerRef.character.Add(ShopItemsList[itemIndex].charactersModel);
DisableBuyButton();
#region "Save the purchased character"
GameManagerRef.mPurchasedCharaters = GameManagerRef.mPurchasedCharaters + GameManagerRef.mCharacterDemiliter + ShopItemsList[itemIndex].charactersModel.name;
PlayerPrefs.SetString("SavedCharacters", GameManagerRef.mPurchasedCharaters);
GameManagerRef.isCharacterPurchased = GameManagerRef.isCharacterPurchased + GameManagerRef.mCharacterDemiliter + ShopItemsList[itemIndex].isPurchased;
PlayerPrefs.SetString("SaveCharacterPurchaseData", GameManagerRef.isCharacterPurchased);
//PlayerPrefs.SetInt("SaveCharacterPurchaseData", boolToInt(ShopItemsList[itemIndex].isPurchased));
#endregion
}
else
{
Debug.Log("You dont have sufficient amount");
}
}
在这里保存角色模型并将其加载回使用playerprefs可以很好地工作。我得到了它的工作,但问题是,一旦我买了东西,它的变化购买。除非你退出游戏并再次回到游戏中。它变成了从购买到再次购买。试着保存字符串,或者我甚至不知道这是否是正确的方式。请帮忙@dgates82。
作为参考,我的GameManager
脚本也因为我一直同时使用它们
public static GameManager Instance;
//Stores Coin Value throughout the game
/*[HideInInspector]*/ public int coin = 0;
//Retreive / Load Coin Value thats saved
int savedCoin;
//Get the LevelManager of that specific scene
[HideInInspector] public GameObject LevelManagerRef;
/*[HideInInspector]*/ public GameObject shopRef;
/*[HideInInspector]*/ public Shop storeShopScript;
public List<GameObject> character = new List<GameObject>();
[Space]
[Header("Save and load store Character Data")]
public string mPurchasedCharaters = string.Empty;
public string isCharacterPurchased = string.Empty;
public string[] mPurchasesCharacterList;
public string[] characterPurchasedList;
public char mCharacterDemiliter = '/';
void Awake()
{
//Loads the coin save Data
LoadCoinSaveData();
#region "Singleton Code"
//Checks to see if there is another gameManager instance and deletes that
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(this); //Singleton
return;
}
Destroy(this.gameObject);
#endregion
}
private void Start()
{
shopRef = FindInActiveObjectByName("ShopMenu");
storeShopScript = shopRef.GetComponent<Shop>();
PopulateCharacters();
//makePurchased();
}
#region "Populate SavedCharacters"
public void PopulateCharacters()
{
mPurchasedCharaters = PlayerPrefs.GetString("SavedCharacters");
if(mPurchasedCharaters == string.Empty)
{
mPurchasedCharaters = "Man";
PlayerPrefs.SetString("SavedCharacters", mPurchasedCharaters);
}
mPurchasesCharacterList = mPurchasedCharaters.Split(mCharacterDemiliter);
foreach (var sub in mPurchasesCharacterList)
{
GameObject loadedCharacter = Resources.Load(sub) as GameObject;
character.Add(loadedCharacter);
}
}
//public void makePurchased()
//{
// isCharacterPurchased = PlayerPrefs.GetString("SaveCharacterPurchaseData");
// characterPurchasedList = isCharacterPurchased.Split(mCharacterDemiliter);
// foreach (string characterSaved in characterPurchasedList)
// {
// for (int i = 0; i <= storeShopScript.ShopItemsList.Count; i++)
// {
// if ()
// {
// storeShopScript.ShopItemsList[i].isPurchased = Convert.ToBoolean(bool.Parse(characterSaved));
// }
// }
// }
//}
#endregion
private void LoadCoinSaveData()
{
savedCoin = PlayerPrefs.GetInt("SavedCoinValue");
coin = savedCoin;
}
//Reduce the coin value depending upon the amount
public void UseCoins(int amount)
{
coin -= amount;
}
//Use coins if enough coins are there?
public bool HasEnoughCoins(int amount)
{
return (coin >= amount);
}
GameObject FindInActiveObjectByName(string name)
{
Transform[] objs = Resources.FindObjectsOfTypeAll<Transform>() as Transform[];
for (int i = 0; i < objs.Length; i++)
{
if (objs[i].hideFlags == HideFlags.None)
{
if (objs[i].name == name)
{
return objs[i].gameObject;
}
}
}
return null;
}
}
正如在评论中提到的,你不能序列化GameObjects,或者任何从MonoBehaviour继承的东西。
所以我们需要首先创建一个可以序列化的类来存储一些相关的数据,并使用"Serializable"属性。
[Serializable]
public class CharacterData // Do not inherit from MonoBehaviour here
{
public int Id;
public string Name;
public int HitPoints;
public int AttackDamage;
}
你的角色游戏对象将使用这个数据
public Character : MonoBehaviour
{
public CharacterData Data;
private int hitPoints;
// Retrieve data from CharacterData for local use
void Awake()
{
hitPoints = Data.HitPoints;
}
}
然后我们将创建另一个可序列化的类来保存我们所有的各种保存数据,非常有创意的命名…SaveData,它有一个字符数据列表作为一个字段。
[Serializable]
public class SaveData // Do not inherit from MonoBehaviour here
{
public List<CharacterData> Characters;
}
现在您可以序列化和反序列化您的SaveData并将其存储在您想要的任何地方
public class SaveManager : MonoBehavior
{
public void Save(SaveData data)
{
// Serialize to json
var jsonData = JsonUtility.ToJson(data);
// Now save the json locally, to GPGS, etc. as you choose
}
public void Load()
{
// Retrieve json data from storage of your choice
var jsonData = somehow get from storage
// Then deserialize it back to an object
var saveData = JsonUtility.FromJson<SaveData>(jsonData);
// And then apply it to your characters
// For example, maybe you instantiate your prefabs and then add the character data
foreach (var characterData in saveData.Characters)
{
var spawnPoint = // need a spawn point
var characterPrefab = // need a prefab to assign
var character = Instantiate(characterPrefab, spawnPoint);
// Assign the saved character data to the new game object
character.CharacterData = characterData;
}
}
}