I am working on a card game of sorts and I've been trying to figure out how to handle unique card effects on the Card class. I've included the class below. I'm trying to add an "effect" property to the class that can be populated in the constructor or later via a setter if needed. The problem I have is I don't know if this method will have a return type or the same return type. The simple way would seem to be to say that effect methods in the game cannot return values and simply define the property as an Action but it's definitely nice to be able to return something in certain situations (mostly testing situations where you might want to confirm the proper Card or List<Card> is returned or even the proper player or deck object).
I'm extremely new to c# and am probably missing something or misunderstanding generics. I've added type object because that gets me out the door with the getter and setter but I don't know if object will inherently allow me to return a class the isn't actually extended from object.
using System;
[System.Serializable]
public class Card
{
public int Id { get; set; }
public string Title { get; set; }
public int Cost { get; set; }
public int Power { get; set; }
public string Description { get; set; }
public Func<object> Effect { get; set; }
public Card()
{
}
public Card(int id, string title, int cost, int power, string description, Func<object> effect)
{
Id = id;
Title = title;
Cost = cost;
Power = power;
Description = description;
Effect = effect;
}
}
I initially tried just defining it as:
private Func<> effect;
public Func<> Effect
{
get { return effect; }
set { effect = value; }
}
I expected that without defining a type it would allow me to return a non-null type but I suspect I'm misunderstanding the usage of generics here.
Proper use of a generic would be e.g.
This would require though that
Carditself is generic as well (Card<T>) with the same type restrictions.The only exception is having a method which allows you to pass in the generic type once you call it
This very much depends on your other code though and how exactly you are intending to consume this property. If you go for generics you will also need to explicitly provide a type when you consume it.
So I just claim now this is most probably not what you wanted to do anyway.
I think instead you might want to rather have something like e.g.
and then rather
this you can pass in via the constructor and consume properly without needing to know/return the exact implementing type.
This will still make little sense in a
[Serializable]class which you configure via the Inspector which will not use any special constructor but rather the default parameter-less one.Alternative Approach
I think in your Unity specific case you would be better of using
ScriptableObjectassets. AScriptableObjectis mainly intended to be a "data container" but in the end it is a c# class so it can also implement own behavior. Something I use to call "scriptable behavior".You create instances of this via the Assets -> right click -> Create -> Card
And then populate it via the Inspector. Later you can use this just as you would e.g. Textures and other assets and drag it into your game managers list for instance.
And then for the
CardEffectyou do the same and have e.g.and then create specific effects like e.g. (I don't know your use case and types of course)
you can create as many subtypes of effects as you wish and reference them in your
Cardinstances. You can even make theCard.Effectrather a list and chain combine multiple effects together.