- Home /
Visualization of saved games inside a Load Menu - Problem with instantiated prefabs
Hi everyone,
I am working on a Load-Save system for a game and currently I am stuck with a bug, which I am unable to resolve. I browsed through Google and this forum and I found similar problems, but nothing so far really worked for me.
When I save my current game progress, I let the user choose a name for that file and I save the time of creation. The resulting filename is a string of the form filename_dd_mm_yyyy_hh_mm.bin where the _ character acts like a separator, separating the name, date and time of the game being saved. Every time I start the game and I go to the Load-Game-menu, I want to display each of my saved files using the following prefab which I called "SlotPanel":
It consists of a button, that, when I press it, loads the saved game. The button contains an image (white area) where I want to display a screenshot of the game when the game was saved. It also contains three text elements, one displaying the name, date and time of the saved file. I am reading this information from the actual file name of the saved game on my hard drive.
Finally, here is the bug. When I am in my Load menu, it looks like this:
I can see in the inspector that the order is correct (I am sorting them according to the file, the least recently created). However, there must be something wrong with the assignment of the information to that prefab. What I observed is there is something like a circular shift, meaning that the information of button 1 gets displayed on button 2, the information of button 2 gets displayed on button 3 and so on. Since there is probably no way around showing you the code, I posted it below. For the better understanding, I am referring to the buttons, that represent a saved file, as "cards". I assign the prefab "SlotPanel" and the parent gameobject (I called it container) through the inspector.
Thank you very much in advance for everyone helping me figure this out! This bug is probably a silly one, but I just can't seem to figure it out.
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class DisplayCards : MonoBehaviour
{
public GameObject slotPrefab;
public RectTransform container;
private Image cardImage;
private Sprite screenshotSprite;
private TextMeshProUGUI saveName;
private TextMeshProUGUI date;
private TextMeshProUGUI time;
private CardFileName cardFileName; // name variable for each card
// reset card information
private void Reset()
{
cardImage = null;
screenshotSprite = null;
saveName = null;
date = null;
time = null;
}
// check if a file has '.bin' extension
private bool HasExtension(string s, string ext)
{
char last = s[s.Length - 1];
char secondLast = s[s.Length - 2];
char thirdLast = s[s.Length - 3];
char fourthLast = s[s.Length - 4];
char[] chars = { fourthLast, thirdLast, secondLast, last };
string substring = new string(chars);
if (substring.Equals(ext))
{
return true;
}
else
{
return false;
}
}
// sort saved files according to date of creation
// lastest created file is on 1st place of the list
private List<FileInfo> SortFiles(List<FileInfo> binaryFiles)
{
binaryFiles = binaryFiles.OrderByDescending(e => e.CreationTime).ToList();
int b = binaryFiles.Capacity;
return binaryFiles;
}
private void CreateCard(string s, int siblingIndex)
{
// create actual card
GameObject loadCard = Instantiate(slotPrefab) as GameObject;
loadCard.transform.SetParent(container);
loadCard.transform.SetSiblingIndex(siblingIndex);
// remember file name
cardFileName = loadCard.GetComponent<CardFileName>();
cardFileName.thisCardFileName = s;
// remove '.bin' extension
string sWithoutExtension = s.Remove(s.Length - 4, 4);
string[] substringlist = sWithoutExtension.Split('_');
// name gameobject
loadCard.name = s;
// create name-, date- and time-textfields
GameObject saveNameObj = slotPrefab.transform.GetChild(0).GetChild(1).GetChild(0).gameObject;
GameObject dateObj = slotPrefab.transform.GetChild(0).GetChild(1).GetChild(1).gameObject;
GameObject timeObj = slotPrefab.transform.GetChild(0).GetChild(1).GetChild(2).gameObject;
saveName = saveNameObj.GetComponent<TextMeshProUGUI>();
date = dateObj.GetComponent<TextMeshProUGUI>();
time = timeObj.GetComponent<TextMeshProUGUI>();
saveName.text = substringlist[0];
Debug.Log("My name is: " + substringlist[0]);
Debug.Log("Instance name is: " + saveName.text);
date.text = substringlist[1] + "/" + substringlist[2] + "/" + substringlist[3];
time.text = substringlist[4] + ":" + substringlist[5];
// find according screenshot-image
GameObject imageObj = slotPrefab.transform.GetChild(0).GetChild(0).gameObject;
cardImage = imageObj.GetComponent<Image>();
string screenshotFolderPath = "Assets/Resources/Screenshots";
DirectoryInfo screenshot_dir = new DirectoryInfo(screenshotFolderPath);
foreach (FileInfo fi in screenshot_dir.GetFiles())
{
if (!HasExtension(fi.Name, "meta"))
{
string imageName = fi.Name.Substring(0, s.Length - 4); // cut out '_Screenshot.png'-part
if (imageName.Equals(sWithoutExtension))
{
byte[] data = File.ReadAllBytes(screenshotFolderPath + "/" + fi.Name);
Texture2D texture = new Texture2D(300, 200, TextureFormat.ARGB32, false);
texture.LoadImage(data);
texture.name = imageName;
Rect rect = new Rect(0, 0, texture.width, texture.height);
screenshotSprite = Sprite.Create(texture, rect, new Vector2(0.5f, 0.5f));
cardImage.sprite = screenshotSprite;
break;
}
}
}
// clear stuff
Reset();
}
// if you save a new game, this function gets
// called to update the list of saved games
public void addToCards(string s, int i)
{
CreateCard(s, i);
}
// iterate over all saved files in hard disk and derive information from file name
private List<FileInfo> GetBinaryFiles()
{
List<FileInfo> binaryFiles = new List<FileInfo>();
string path = Application.persistentDataPath + "/";
DirectoryInfo saveDirectory = new DirectoryInfo(path);
if (!saveDirectory.Exists)
{
Debug.Log("Directory doesn't exist!");
return null;
}
foreach (FileInfo fi in saveDirectory.GetFiles())
{
if (HasExtension(fi.Name, ".bin") && !fi.Name.Equals("options_saved.bin"))
{
binaryFiles.Add(fi);
}
}
return binaryFiles;
}
void Start()
{
List<FileInfo> binaryFiles = GetBinaryFiles();
binaryFiles = SortFiles(binaryFiles);
for (int i = 0; i < binaryFiles.Count; i++)
{
CreateCard(binaryFiles[i].Name, i + 1);
}
}
}
Your answer
Follow this Question
Related Questions
Terrain: Use as scenario (individual) and prefab (unchanged, reusable) 0 Answers
How to reduce time of instantiating a prefab that contains many objects/components in it. 1 Answer
Load a grid of cubes in the scene view before running level? 2 Answers
Get object/prefab name as string. 1 Answer
How do you make a script that creates a new scene on runtime? 1 Answer