- Home /
How to handle identifying duplicate scriptable objects?
Hello, I'm working on a card based game where the cards are scriptable objects (shown below)
public class Card : ScriptableObject
{
public string cardName;
public string description;
public Sprite sprite;
public int baseDefense;
public int baseWealth;
public int baseAttack;
}
and I have a Deck object that persists between scenes and holds a List of all the player's (scriptable object) cards:
I'm looking for a way to tell how many times a specific card has been played, but this becomes a problem for duplicate cards, because I can't simply increment a number on the scriptable object card (it would update on all cards of that type). So if (for example) I wanted to keep track of how many times the element 4 card had been played without updating all the other "farmer cards", how should I go about that? Should I give up on scriptable objects and just use a gameobject instead? Another detail: cards are not removed from this deck when they're played, they're added to a new and separate draw and discard List, but there are still times where cards are added and removed from the deck. Thanks.
Answer by Kona · Aug 29, 2021 at 08:43 PM
You could create a manager object to keep track of the card count. I'ld add a new property to the card SO's to identify type of card eg:
public enum CardTypeNames {
Beggar_Card = 0,
Farmer_Card = 1,
Squire_Card = 2,
Nihil_Card = 3
}
And then in your Scriptable Object, adding a "CardTypeNames" value.
Now whenever you pull a new card send this new property to a card manager which will keep track of the cards in a list, array or whatever feel most comfortable.
public static class CardManager {
public static int[ , ] cardCounts;
//Creates a new 2D array to keep track of cards
//Make sure to call "CardManager.ResetCardArray()" when a map / session is loaded
public static void ResetCardArray() {
cardCounts = new int[ System.Enum.GetValues( typeof( CardTypeNames )).Length, 1 ]();
}
public static void IncreaseCardCount( CardTypeNames card ){
cardCounts[ (int)card, 0 ]++; //Increase the count of target card
}
public static void ReduceCardCount( CardTypeNames card ) {
cardCounts[ (int)card, 0 ]--; //Reduce the count of target card
}
public static int GetCardCount( CardTypeNames card ) {
return cardCounts[ (int)card, 0 ]; //Retrieve the amount of cards of specified type that exist
}
}
Notice that in my example the cardCount array is not assigned by default, since it use Enum.GetValues to determine the size of one dimension therefore, one would have to call "CardManager.ResetCardArray();" whenever a new map is loaded.
Thanks for the reply! Using a 2d array had popped into my $$anonymous$$d, but I haven't used them before, so I wasn't sure how to implement it--this looks like a good template. The current solution I came up with was to generate a new scriptable object whenever a card is added to the deck (this function is called whenever a card is added to the deck):
private Card CreateCardInstance(Card card)
{
Card newCard = ScriptableObject.CreateInstance<Card>();
EquateCardValues(newCard, card);
newCard.index = deckIndexNumber;
deckIndexNumber++;
newCard.name = card.name;
return newCard;
}
where EquateCardValues just copies the values from the old card ("old card" being the scriptable object cards that exist outside of runtime) to the new one, but I imagine this is pretty wasteful in terms of processing. I also added an index number to the card so each one would have a unique number. I'll probably do some experimenting with the array method you suggested as well to see if I can get that working. Thanks!
If I'm not mistaken Scriptable Object's are meant to be used to store data shared by several objects, eg. If you have an object holding 5 properties and create 20 instances of said object- that means you are shoving 100 properties into memory ( 5 x 20 ), if those objects instead only had 1 property, a reference to an SO that is, only 5 properties are present since the SO is shared by all instances. ( Don't take this literally, I could be wrong and it's certainly not 100% accurate, but it's the rough idea I have of how ScriptableObject works. )
So yes, generating new instances of a template SO could be wasteful- but in the end, as long as it works it's allright I guess. :)
Yes, do experiment with the 2Darrays, multi-dimensional arrays are a great tool, if not necessary to you now it could surely be helpful in the future! :)
Your answer
Follow this Question
Related Questions
ScriptableObjects lists (from the same script) open simultaneously in custom window 0 Answers
Help: items not getting added to list. 1 Answer
Add every ScriptableObject to a list? 1 Answer
List keeps emptying itself 0 Answers
How to compare a string in a list with a gameobject.name from another list of gameobjects 1 Answer