1

I have this ScriptableObject and I would like to add an effect to each card at creation; I have a script called "EffectManager" that has some methods as effects.

This is my card script

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(fileName = "New Card", menuName = "Card")]
public class Card : ScriptableObject
{
    public string m_cardName;
    public Sprite m_sprite;

    public int m_manaCost;
    public int m_health;
    public int m_attack;
}

and this is my EffectManager Script

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class EffectManager : MonoBehaviour
{
    Deck dk;
    Hand hnd;
    Player p1;
    
    private void Awake()
    {
        dk = GameObject.FindObjectOfType<Deck>();
        hnd = GameObject.FindObjectOfType<Hand>();
        jg1 = GameObject.FindObjectOfType<Player>();
    }

    public void draw(int num)
    {
        jg1.DrawCards(num);
    }

    public void discard()
    {
        hnd.hand.RemoveAt(0);
    }

    private void mill()
    {
        dk.deck.RemoveAt(0);
    }
}

How can I make so each card I create has an effect linked to it that activates when conditions are met? (in this case it would be when the card is summoned)

Cobalixe
  • 11
  • 2

1 Answers1

1

You could use a pattern I like to call "Scriptable Behavior" which basically simply consists of another ScriptableObject type and implement different effects like e.g.

public abstract class CardEffect : ScriptableObject
{
    // You can give that the signature (parameters and return type) you want/need of course
    // Every type inherited from this HAS TO implement this method
    public abstract void ExecuteEffect (EffectManager effectManager);
}

Now you can implement certain configurable effects like e.g.

public class DrawEffect : CardEffect
{
    // Adjust how many cards are drawn
    public int amount;

    public override void ExecuteEffect (EffectManager effectManager)
    {
        effectManager.draw(amount);
    }
}

Or e.g.

public class DrawAndDiscardEffect : DrawEffect
{
    public override void ExecuteEffect (EffectManager effectManager)
    {
        // First do whatever the parent class implements
        base.ExecuteEffect(effectManager);

        // Additionally discard the same amount of cards
        for(var i = 0; i < amount; i++)
        {
            effectManager.discard();
        }
    }
}

Finally you would have an additional field in the card definitions. Personally I would even use an array so you can totally flexible combine different kinds of effects without having to inherit one from another like

public class Card : ScriptableObject
{
    public CardEffect[] effects;

    ...

    public void Summon(EffectManager effectManager)
    {
        foreach(var effect in effects)
        {
            effect.ExecuteEffect(effectManager);
        }
    }
}

Now all that's left is that something in your setup actually calls that

// Wherever you get these from
EffectManager effectManager;
Card someCard;

someCard.Summon(effectManager);

This then can easily be extended to the comolexibility you need. You could e.g. instead of having a Summon method and only one collection of effects have yet another ScriptableObject type called EffectCondition and implement different types of conditions which will then run their attached effect collection.

Then the central controller could go through all cards and rather call e.g. CheckCondition and then every card goes through all attached conditional setups, checks if the according condition is fulfilled and then executes all effects bound to that condition ;)

derHugo
  • 83,094
  • 9
  • 75
  • 115
  • Question though: What I have seen is, people create Scriptable Object using[CreateAssetMenu(attribute)]. If I have so many Scriptable Behaviour( I have 60 cards, each has 4 CardUpgrade), How do I create those assets? – Zony Zhao Sep 29 '22 at 11:13
  • @ZonyZhao well, you would create them yes .. the one or other way you have to fill in this information. Do all your 60 cards have completely unique effects? – derHugo Sep 29 '22 at 12:40
  • It's not visual effects, but card behaviour, like, the usage of the card. Of course they are different. Maybe I can abstract them to a certain degree, but it's at lease 20-30 I guess? U can just take Hearthstone card as reference. – Zony Zhao Oct 02 '22 at 02:27
  • In that case I would probably still go with ScriptableObjects.. or just have "normal" classes derived from a base card and instantiate them where needed via reflection e.g. – derHugo Oct 02 '22 at 06:00