- Home /
The question is answered, right answer was accepted
Scriptableobject List and Instantiating objects from it
Hello, I am making a simple scriptableobject inventory to store the objects of a in-game store. All was good and wall until it came to the part where I need to instantiate all of the objects from that list and it only instantiates the last one from the list no matter what I tell it to do.
For example I try doing this:
public List<GameObject> gameStoreInventory = new List<GameObject>();
public GameDatabase gameDatabase;
public GameObject slotHolder;
private void Start()
{
PopulateGames();
}
public void PopulateGames()
{
GameObject obj = Instantiate(gameDatabase.games[0].GamePrefab) as GameObject;
gameStoreInventory.Add(obj);
obj.transform.SetParent(slotHolder.transform, false);
}
}
And I'm trying to instantiate the first item in the list but for some reason the last time in the list would always instantiate instead.
The scriptableobject script is this one:
[CreateAssetMenu(menuName = "New Game Database")]
public class GameDatabase : ScriptableObject
{
public List<Games> games = new List<Games>();
public enum GameType { Action, Adventure, RPG, Puzzle, FPS, RTS };
public enum GameQuality { Bad, Decent, Good };
[System.Serializable]
public class Games
{
public GameObject GamePrefab;
public string Name;
public string Description;
public GameQuality GameQuality;
public GameType GameType;
public string Review;
public int Cost;
}
}
And every item that is set in that list has this script attached to it:
public class Game : MonoBehaviour
{
public Text Name;
public Text Description;
public Text Quality;
public Text Genre;
public Text Review;
public Text Cost;
public GameObject GamePrefab;
public GameObject tooltip;
public GamesManager gamesManager;
private void Start()
{
gamesManager = GameObject.Find("Game Store Menu").GetComponent<GamesManager>();
}
private void Update()
{
for (int i = 0; i < gamesManager.gameDatabase.games.Count; i++)
{
Name.text = gamesManager.gameDatabase.games[i].Name;
Description.text = gamesManager.gameDatabase.games[i].Description;
Quality.text = gamesManager.gameDatabase.games[i].GameQuality.ToString();
Genre.text = gamesManager.gameDatabase.games[i].GameType.ToString();
Review.text = gamesManager.gameDatabase.games[i].Review;
Cost.text = gamesManager.gameDatabase.games[i].Cost.ToString();
GamePrefab = gamesManager.gameDatabase.games[i].GamePrefab;
}
}
This is how the scriptableobject list looks like in the inspector:
And this is how it look's like I explained above where no matter what I do the last item is always being displayed:
Does anyone have any tip's on how to fix this? What I doing something wrong? Thanks in advance!
Every GamePrefab object instantiated in the scene has Game $$anonymous$$onoBehaviour attached, right? Why are you loooping through all games in gameDatabase and set all the credentials every tick? It seems to me that you set all of these texts every frame so actually you see the object as the last one. Every frame you change all of texts components, so you should see rapid flickering or random still text.
Answer by FernandoHC · Aug 27, 2018 at 10:16 AM
First, Whenever having this kind of error, where you are getting one thing instead of the other, always make the differences between the objects to have as discrepancy as possible. In your cases I see the objects are exactly the same, save the name that changes only one character. That in itself is a cause for confusion.
Secon, why are you setting the values on an Update, and with a for? Not sure where your Game class is assigned to, but what is happening there is that you're going through your whole "gameDatabase" on each update frame, and assigning all values to the Game class public variables, only the last values will be displayed, because it as the last one put in. So if you want to make this work you have to assign the values only at the time the object is instantiated and never again.
On a side note, do not recommend calling a class "Game" unless it really is a singleton game manager class.
Answer by misher · Aug 27, 2018 at 10:47 AM
You should work on clear separation of DATA, UI and other Controllers Scripts.
You can define all data in several ScriptableObjects. Having a prefab as a data is really a bad practice, this is the task of UI part, your evety UI script should contain references to own ui template (it can be also a disabled gameobject somewhere in your canvas somewhere not strictly a prefab) and then instantiate this template with using provided data. I would recommend you also to pass events through Scriptable Objects as well as it can make your architecture loosely coupled, here you can find a simple and powerful architecture pattern:
Answer by RX187 · Aug 27, 2018 at 07:37 PM
@Sonky108 @FernandoHC @misher Thank you all for you answers and tips I will take those into account. So far I have managed to solve the problem with you said, I can't believe I didn't realize the mistake with the for loop thing in the update sooner.