【发布时间】:2021-10-10 11:24:33
【问题描述】:
所以我有这个
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;
}
}
【问题讨论】:
-
关于上面的链接,最相关的在this answer下,你应该考虑JSON序列化。
-
你不能直接保存游戏对象,因为它们包含的状态必须绑定到当前会话(例如渲染器或当前位置)。相反,每个角色都应该有一个 ID。当玩家解锁新角色时,您应该保存当前角色的标识符 - 您可以使用逗号分隔的字符串,类似于
"character1_id,character2_id"。当会话开始时,读回这个值并正确地实例化字符。 -
@CoderCharmander 可以简要介绍一下如何实现这一目标
-
@DekuDesu 但我如何将列表数组存储到 json 中。我们通常不能在 json 上存储列表,对吧?