Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by JoshuaSilvestre · Jul 28, 2020 at 07:31 PM · prefabscriptableobjecteffectsarchitecturecards

Optimal architecture for card effects, prefabs or scriptableobjects?

Hi all, I am making a turn based CCG for fun and educational purposes. At the moment I have a system in place for creating card effects, it is usable but not up to the standard I would like to have.

Current System:

Each effect contains 3 main properties:

- A list of triggers

A trigger is an event in the game world

Example: When a card is played

- A list of conditions

Conditions are the necessary states needed in order to execute the effect action

Example: If the player has more than x life

- A list of effect actions

An effect action alters the state of the game/player/card in some way

Example: Deal x damage to the opponent

The problem with the current system:

This system requires me to create a new game object for each card effect. There is no need for this to be a game object. Also, any trigger,condition or effect action that the card uses must be attached to the game object. This can lead to a very cluttered inspector view on more complex effects. As previously stated, this works but I feel it can be improved upon and can't seem to figure out how.

Alternatives:

I have played around with scriptable objects without much success. For example, if I had an EffectAction class called DealDamageToPlayer, anytime I want to use this class on an effect; I would need to create a new instance because it would alter the original value. This would leave me with multiple copies of the same class all with different values. Also, I understand that this also occurs with the current system, when I attach the same script to multiple effect game objects. The difference is that it is not visible in the project explorer and does not result in clutter.

Similar Questions:

My original system was inspired by this question 'What is the most effective way to structure Card Effects in a Single Player game?' They ran into the same issue I mentioned in the alternatives section with regards to scriptable objects.

This question: 'Card Game, cards as ScriptableObject, card effects as ScriptableObjects, effects have different parameters. How to make an inspector UI support this structure?' includes the type of UI I am after. However, because they use scriptable objects there will be many duplicate instances.



If anything I said is incorrect, please do correct me.

Any and all assistance would be greatly appreciated.

Scripts:

Trigger.cs

 public abstract class Trigger : MonoBehaviour
 {
     public abstract void SubscribeToEvent(Action<EventInfo> checkConditions);

     public abstract void UnsubscribeFromEvent(Action<EventInfo> checkConditions);
 }



Condition.cs

 public abstract class Condition : MonoBehaviour
 {
     public abstract bool Requirement(EventInfo eventInfo);
 }



EffectAction.cs

 public abstract class EffectAction : MonoBehaviour
 {
     public abstract void ApplyEffectAction();
 }



Effect.cs

 public class Effect : MonoBehaviour
 {

     [Header("WHEN")]
     public List<Trigger> triggers;

     [Header("IF")]
     public List<Condition> conditions;

     [Header("DO")]
     public EffectAction effectAction;

     public void SetUpTriggers()
     {
         foreach (Trigger trigger in triggers)
         {
             trigger.SubscribeToEvent(CheckConditions);
         }
     }

     public void RemoveTriggers()
     {
         foreach (Trigger trigger in triggers)
         {
             trigger.UnsubscribeFromEvent(CheckConditions);
         }
     }

     public void CheckConditions(EventInfo eventInfo)
     {
         if (conditions.Count != 0)
         {
             foreach (Condition condition in conditions)
             {
                 if (!condition.Requirement(eventInfo))
                 {
                     Debug.Log("CheckConditions: false");
                     return;
                 }
             }
         }
         effectAction.ApplyEffectAction();
     }
 }



Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image ducthangdang1502 · Jan 28, 2021 at 09:38 PM 0
Share

Hello, I am currently trying to make such a game too. Are you still active on this one? Is there a way I can communicate with you further?

1 Reply

· Add your reply
  • Sort: 
avatar image
2
Best Answer

Answer by xxmariofer · Jul 29, 2020 at 07:44 AM

Hello, i would go with a little different approach, but this is just an idea, i would make Effect class a ScriptableObject and add the createassetlabel to create instance of effects in the project folder. Second i would NOT create an instance for each EffectAction for example, step by step for what i would do, this example is only based on the EffectAction class, i would first create an enum with all the effects posible

 public enum EffectDataType
 {
     heal,
     damage,
     powerup
 }

second, when you are using instance of EffectAction i would simply use a struct, serializable so that can be edited in the scriptablobject inspector with all the damage/cost and data needed

 [System.Serializable]
 public struct EffectActionData
 {
     public EffectDataType type;
     public int damage;
     public int cost;
     public string name;
 }

then i would create your effectaction parent class and a damage child for example

  public abstract class EffectAction
  {
      public abstract void ApplyEffectAction(EffectActionData data);
  }
 
  public abstract class DamageAction: EffectAction 
  {
      public virtual void ApplyEffectAction(EffectActionData data)
      {
           Debug.Log("logic");
      }
  }

and finally create the effect scriptable object class

 [CreateAssetMenu(fileName = "Data", menuName = "ScriptableObjects/Effect", order = 1)]
 public class Effect : ScriptableObject 
 {
     public EffectActionData cardEffect;
     public void CheckConditions()
     {
         //if (conditions.Count != 0)
         {
             //  foreach (Condition condition in conditions)
             {
             //    if (!condition.Requirement(eventInfo))
                 {
                     Debug.Log("CheckConditions: false");
                     // return;
                 }
             }
         }

         switch (cardEffect.type)
         {
             case EffectDataType.damage:
                 Debug.Log("Here you would call to the ApplyEffectAction method that could even be static so you dont need instances");
                 break;
             case EffectDataType.heal:
                 break;
             case EffectDataType.powerup:
                 break;
         }
     }
 }
Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image JoshuaSilvestre · Jul 30, 2020 at 05:58 PM 0
Share

Thank you for the detailed response. After looking at your answer and discussing the problem with other game developers, I now see the initial problem with my implementation.

Because the EffectAction and value were included in one class, this required me to create a new instance of the class each time I wanted to use a different value. This is unnecessary as the only thing that is changing is the value that the action uses and not the actual function.

If I remove the value from the EffectAction class, I am now required to pass in a value to the ApplyEffect function. This creates a new problem as different EffectAction classes require different input parameters. As you demonstrated this can be solved by creating a struct to hold the required data, now we can pass the same object type to each EffectAction.

The next problem to tackle is how do we know which EffectAction to call. At the moment I am debating between your suggested method (Solution 1) and Solution 2.

Solution 1: In your answer you used a switch case and EffectActionType enum. The EffectActionType would allow me to select the type of EffectAction to call. To add a new EffectAction I would be required to add a new entry to the enum and the switch case.

Solution 2: $$anonymous$$ake the EffectAction a scriptable object, this allows me to drag the type of EffectAction I wish to use in the inspector. Although, now to use an EffectAction you are required to have a direct reference. Whether this might cause issues later on, I don't know. To add a new EffectAction I would only be required to create the new EffectAction class.

I am curious what you think of Solution 2. If you see any obvious problems with it, please do let me know.

avatar image xxmariofer JoshuaSilvestre · Jul 30, 2020 at 07:32 PM 0
Share

i dont see any issues with your second approach, looks totally fine to me

avatar image JoshuaSilvestre · Jul 30, 2020 at 07:41 PM 0
Share

Sounds good.

Thanks for the help I appreciate it.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

175 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Using Part of prefab as script parameter 1 Answer

Add a GameObject as a sub-asset of a ScriptableObject 1 Answer

is having a Prefab reference inside a a Scriptable Object legit? 0 Answers

Using ScriptableObjects to build ECS archetypes 0 Answers

High Level Architecture for Book App 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges