Assigning specific class variable

I am working on a small card game style project. I have a custom class for the cards. The code is:

using UnityEngine;
using System.Collections;

    public enum SpeciesType{
        Human,
        Orc,
        Elf,
        Alien,
        Monster,
        Loner
    };

    [System.Serializable]
    public class Card{
        public SpeciesType species;
        public string cardName;
        public int health;
        public int armour;
        public int attack;
        public int intelligence;
        public int stamina;   

        public Card(SpeciesType spec, string name, int hp, int arm, int at, int intel, int stam){
            species = spec;
            cardName = name;
            health = hp;
            armour = arm;
            attack = at;
            intelligence = intel;
            stamina = stam;
        } 
    }

My question is can I assign a specific card element into a general variable I can access via scripts?
Can i do something like this:

general variable = cards health;
if(player card general variable > AI card general variable){
the player wins
}

My game works so whoever has the higher number in the specific variable, in this example health, then they win and the defeated card goes to the dead pile.

The idea being that, if i choose attack, then I can assign the general variable to attack, without having to do multiple If statements for each class int. This is my first time using a custom class. Sorry if it’s hard to understand, it’s weird to explain. I dont know if this even a thing

What do you mean with “custom class for the cards”? There is no “general class for the cards” to my knowledge.
“This is my first time using a custom class.” - You mean first time writing your own class?

Also your fields in card class are public so you could just (from example you have provided):

if(playerCard.health > AICard.health){
//the player wins
}

If you though you could get throught this without multiple comparisons (? - I am refreing to “without having to do multiple If statements”), you’re gonna have to wait for someone smarter than me. (if that’s even possible)

Yes, this is my first time writing my own class. It’s all a bit weird to me, but I’m learning.
The code you posted works, but that means I’d have to do an if statement for health, armour, attack, intelligence and stamina, which I am hoping to avoid. I dont know if it is even a thing that’s possible.

There sometimes isn’t anything wrong with multiple if statements.

but if all you’re wanting is to compare two values, just have a method that compares it.

public bool CompareValues(int playerNum, int aiNum)
{
    if(playerNum > aiNum)
       return true;
    else
      return false;
}

Then just pass the two values. If the first is greater, you’ll get your true and you know the player won that round.

It depends on how you want to play your game. When does which variable gets compared?
You want to compare one particular variable like health only or compare all and get an average or does the player choose what variable of the card gets compared…?
If you can tell how it should work exactly then it’s easier to help :wink:

If all your attributes were in an array, then you could simply reference them with an index. Your code would then read:

if(player.stats[0] > ai.stats[0])
    // player wins

To keep your card class readable, you could write an indexer for it. Check out this tutorial to see how.

Just another thought here, you could possibly implement the IComparable interface in your class, and then code a CompareTo function. There’s some details here on how to do it in C#: IComparable Interface (System) | Microsoft Learn

You could also create a different function in your class, if you feel more comfortable with that.

The general idea is that you could then do something like… (this is how you’d use the CompareTo function):

if (firstObject.CompareTo(secondObject) > 0) {
  //   firstObject wins...
} else if (firstObject.CompareTo(secondObject) == 0) {
  // tie
} else {
//   secondObject wins...
}

So that’s how you’d USE the CompareTo once it’s coded… as far as coding the CompareTo, there’s a bit more to it, but a lot of it would be based on doing your comparisons of individual values, and then when you’ve compared all the values you need to, you’d return a -1 for less than, 0 for equal, 1 for greater than…

There are some obvious advantages to this, one of which is you keep it in your class, so if your class definition changes, you will hopefully know “oh yah, I need to change the CompareTo as well”… and you won’t have to go hunting through code to figure out where else you need to change your conditionals.

I honestly haven’t implemented IComparable in a while, and it wasn’t in Unity, but I’m pretty certain it would work there, and I think it’s a pretty slick way of doing what you need to do, as I’m sure I can see you ‘recycling’ this check throughout your project. As such, my ability to walk you through it is pretty limited, but there’s a lot of examples out there.

Implementing IComparable also lets you sort a list of your objects too. So if you had an array of cards you could call the .sort method on then. Then when you iterate through them, they’re in some sort of order (that you set in the CompareTo).

Some others might have better suggestions than using IComparable (i.e. some other interface to implement, or suggest you code your own custom function instead). For your own game here, a custom function might work better, but I’d definitely recommend coding a function in your class to do the comparison, so there’s one place that manages that (and therefore only one place to change if your class changes). Not sure if you have the comfort level to try something like this, being new to classes, by the sounds of it… but I think it would help do what you need to do in a nice clean way.

EDIT: I’ll leave this here, but this was more if you were just going to do a whole compare of objects to each other… I just realized right now that you meant to just do a comparison of one field to the same field in another object (which explains my one question I had… what happens if some fields in one object are greater than the other, but the reverse true for other fields). Anyways, I’ll leave my reply here intact anyways.

1 Like

I would ask why you want to do this.
Sure there are lots of ways this might be accomplished but will it gain any speed. Probably not.
Could it make the code unclear as to what is happening? Probably.
Unless there is another reason I would look for the solution that makes the code the most clear.
Not the fewest number of lines. Especially if this is your first time using classes.
Experiment using a class as a class and not trying to make it into another type of data structure or pattern.

You could just assign a lambda function for each comparison and store it in a delegate. But this would not make the code clear.

There are other ways already mentioned that keep it clear about what is being compared.

you could use reflection to get all the fields and properties (and their values) of a type and put them in an array… and then do something like @NoBrainer-David suggested.

Thankyou for all the ideas. I’m going to try them and see how they work. For @jister , my idea was something like:

public ClassField selectedField;

selectedField = Card.health;
if(Player.selectedField > AI.selectedfield){
 // player wins
}

I would strongly advise against a solution with reflection. It adds a complexity to your code that really isn’t necessary right now.

I went ahead and supplemented your code with the indexer for the card stats together with an enum, that makes using the indexer nicer.

public enum SpeciesType
{
Human,
Orc,
Elf,
Alien,
Monster,
Loner
};

public enum CardStat
{
Health = 0,
Armour = 1,
Attack = 2,
Intelligence = 3,
Stamina = 4
}

[System.Serializable]
public class Card
{
public SpeciesType species;
public string cardName;
public int health;
public int armour;
public int attack;
public int intelligence;
public int stamina;

public Card(SpeciesType spec, string name, int hp, int arm, int at, int intel, int stam)
{
species = spec;
cardName = name;
health = hp;
armour = arm;
attack = at;
intelligence = intel;
stamina = stam;
}

public int this[int index]
{
get
{
switch (index)
{
case (int)CardStat.Health:
{
return health;
}
case (int)CardStat.Armour:
{
return armour;
}
case (int)CardStat.Attack:
{
return attack;
}
case (int)CardStat.Intelligence:
{
return intelligence;
}
case (int)CardStat.Stamina:
{
return stamina;
}
default:
{
return -1;
}
}
}
}
}

Then here is a simple script to show you, how to use this.

using UnityEngine;

[ExecuteInEditMode]
public class CompareCardExample : MonoBehaviour
{

    public Card playerCard;
    public Card aiCard;
    public CardStat statToCompare;

    public void OnGUI()
    {
        if (playerCard[(int)statToCompare] > aiCard[(int)statToCompare])
        {
            GUILayout.Label("Player Wins with " + playerCard.cardName + " against " + aiCard.cardName + " in " + statToCompare.ToString());
        }
        else if (playerCard[(int)statToCompare] == aiCard[(int)statToCompare])
        {
            GUILayout.Label("There's a draw with " + playerCard.cardName + " against " + aiCard.cardName + " in " + statToCompare.ToString());
        }
        else
        {
            GUILayout.Label("AI Wins with " + aiCard.cardName + " against " + playerCard.cardName + " in " + statToCompare.ToString());
        }
    }

}

Thankyou @NoBrainer-David , I will try that code tomorrow.
In the example script, why did you remove ‘using System.Collections’? I dont know what it does exactly, but it’s there by default so I just leave it.

I wasn’t using any classes in the System.Collections namespace, so I removed it from the script. It doesn’t really matter, though.

the using parts are namespaces, it’s like a package of “functionality” you can add to you’re script.
Like using UnityEngine; provides you with al the unity goodies: GameObject, Transform, Vector3,… almost everything you find in the Docs.
System.Collection.Generic is a C# namespace from microsoft. It provides things like: List, Dictionary, HashSet,… (System.Collections.Generic Namespace | Microsoft Learn)

@NoBrainer-David , I tried your index its. It works perfectly, thankyou very much.