Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question How do I modify a method

Discussion in 'Scripting' started by unity_lGs5NAP5uLt_sg, Aug 21, 2023.

  1. unity_lGs5NAP5uLt_sg

    unity_lGs5NAP5uLt_sg

    Joined:
    Jun 20, 2019
    Posts:
    3
    I am making a card game and each card has a different way they act when attacking and getting hurt. For example, some cards attack the closest enemy, but others attack a random enemy with splash damage. How do I achieve this? It would look something like this:

    Code (CSharp):
    1. public class Card
    2. {
    3.     public int health;
    4.     public int damage;
    5.    
    6.     public void Attack() {}
    7. }
    8.  
    9.  
    10. public void SwordsmanAttack() {
    11.     Card enemy = FindClosestEnemy();
    12.     enemy.health -= this.damage;
    13. }
    14.  
    15. // if the player buys a new card, I create a new object of Card class and if it is, for example, a swordsman I do Attack() = SwordsmanAttack()
    I hope you understand what I want to achieve. Thanks!
     
  2. unity_lGs5NAP5uLt_sg

    unity_lGs5NAP5uLt_sg

    Joined:
    Jun 20, 2019
    Posts:
    3
    After further research, I found that I may be able to use inheritance for it.
     
    Bunny83 likes this.
  3. AngryProgrammer

    AngryProgrammer

    Joined:
    Jun 4, 2019
    Posts:
    435
    You can also try the alternative of prefabs and variants, similar ideas but fit better in Unity logic.
     
    unity_lGs5NAP5uLt_sg likes this.
  4. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,917
    A simple way is adding a "creatureType" to the class and keying off of that, something like:
    Code (CSharp):
    1. void doCardAttack(Card c) {
    2.   if(c.creatureType==1) SwordsmanAttack(c);
    3.   else if(c.creatureType==2) PantherAttack(c);
    4.   ... and so on
    5. }
     
    unity_lGs5NAP5uLt_sg likes this.
  5. dlorre

    dlorre

    Joined:
    Apr 12, 2020
    Posts:
    700
    You probably want to use ScriptableObject for this, but yes you can do it with inheritance. Interfaces work too but inheritance is more straightforward. Hardcoding creature type like that does not seem to be a good idea to me, because if you have 154878 different cards your code will be hard to read.
     
    Chubzdoomer likes this.
  6. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    I personally use Inheritance myself, so I agree. :D
    Code (CSharp):
    1. public class Card : Monobehaviour
    2. {
    3.     public int health;
    4.     public int damage;
    5.    
    6.     public void AttackOtherCard(Card card)
    7.     {
    8.         card.health -= damage;
    9.     }
    10. }
    11.  
    12. public class Swordsman : Card
    13. {
    14.     void Awake()
    15.     {
    16.         health = 2500;
    17.         damage = 1500;
    18.     }
    19. }
    In your simple example of asking, it simply is just that. However if you want to know more complicated ways of using Inheritance, then ask accordingly.
     
    Bunny83 likes this.
  7. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,844
    Another option is to compose a series of card effects onto a single card class (serialize a polymorphic list of plain C# objects), which you can do with SerializeReference:

    Code (CSharp):
    1. public class Card : ScriptableObject
    2. {
    3.  
    4.     [SerializeReference]
    5.     private List<CardEffectBase> _cardEffects = new List<CardEffectBase>();
    6.  
    7.     public void ActivateCardEffects(CardActivateParams activateParams)
    8.     {
    9.         int effectCount = _cardEffects.Count;
    10.         for (int i = 0; i < effectCount; i++)
    11.         {
    12.             var effect = _cardEffects[i];
    13.             effect.ActivateCardEffect(activateParams);
    14.         }
    15.     }
    16.  
    17. }
    18.  
    19. [System.Serializable]
    20. public abstract class CardEffectBase
    21. {
    22.     public abstract void ActivateCardEffect(CardActivateParams activateParams);
    23. }
    24.  
    25. [System.Serializable]
    26. public sealed class CardEffectDamage : CardEffectBase
    27. {
    28.     public override void ActivateCardEffect(CardActivateParams activateParams)
    29.     {
    30.         foreach (var target in activateParams.Targets)
    31.         {
    32.             // deal damage
    33.         }
    34.     }
    35. }
    36.  
    Does need custom inspector support, though if you don't have that option you can also use scriptable objects instead.

    I think a card game would benefit greatly from being primarily data driven. The top-level systems shouldn't really care what any given card does, it just tells the cards to do their thing.
     
    Last edited: Aug 22, 2023
    NeedsLoomis and dlorre like this.