Interactive with item using condition and command interfaces

Hi all. I would like to implement an interactive item system that the player can interact with items. I program interfaces condition and command and implement them like below:

public class CItemScene : MonoBehaviour {
       
        CBaseCondition[] m_conditions;      
        CBaseCommand[] m_commands;
        CBaseCommand[] m_failCommands;
        CPlayerInputController m_playerinputController;       
        [SerializeField]
        CBaseItemData m_interactiveItemData;
        Transform m_failCommandChildTr;
        Transform m_commandChildTr;
        public int m_id { get; private set; }
       
        public Sprite m_sprite { get; private set; }
        public Animator m_animator { get; private set; }
        // Use this for initialization
        void Start() {
            m_playerinputController = CGameManager1.GetInstance().m_player.GetComponent<CPlayerInputController>();
            m_id = m_interactiveItemData.id;
            m_sprite = m_interactiveItemData.sprite;
            m_animator = m_interactiveItemData.animator;
            m_conditions = transform.FindChild("Conditions").GetComponentsInChildren<CBaseCondition>();

            m_commandChildTr=transform.FindChild("Commands");
            if (m_commandChildTr != null) {
                m_commands = m_commandChildTr.GetComponentsInChildren<CBaseCommand>();
            }

            m_failCommandChildTr = transform.FindChild("FailCommands");
            if (m_failCommandChildTr != null) {
                m_failCommands = m_failCommandChildTr.GetComponentsInChildren<CBaseCommand>();
            }
            
           
        }
        bool CheckAllConditions() {
            for (int i = 0; i < m_conditions.Length; i++) {
                if (!m_conditions[i].CheckCondition()) {
                    return false;
                }
            }
            return true;
        }
        void ExecuteCommands() {
            if (m_commands!=null) {
                for (int i = 0; i < m_commands.Length; i++) {
                    m_commands[i].Command();
                }
            }
         
        }
        void FailCommands() {
            if (m_failCommands != null) {
                for (int i = 0; i < m_failCommands.Length; i++) {
                    m_failCommands[i].Command();
                }
            }
        }
        void Interact() {
            bool checkedFlag = CheckAllConditions();
            if (checkedFlag) {
                ExecuteCommands();
            }
            else {
                FailCommands();
            }

        }
        void OnTriggerStay2D(Collider2D _coll) {
            if (_coll.tag=="Player") {
                if (m_playerinputController.CheckPressedKeyDown(EKeyType.Action)) {
                    Interact();
                }
            }
        }
    }
}

if conditions are true then commands are executed else fail commands are executed.
I want to use general conditions(combination conditions like or and not etc) rather than only “And” conditions,
so I implemented OR,And,Not module conditions like below:

public class CORCondition:CCondition{
CCondition c1;
CCondition c2;
public override bool CheckCondition(){
return c1.CheckCondition() || c2.CheckCondition();
}
}

The first way I can combine conditions and get only result condition like (cresult=(c1 or c2) and (c3 and c4)) and assign it to m_conditions inside my code.
The second way I can put them all as gameobjects(condition components postfix or prefix orders) like below:(children of Conditions)
-Conditions
–condition1
–condition2
–orcondition
–condition3
–condition4
–andcondition
–andcondition
then compute the result condition using postfix or prefix order
m_conditions = transform.FindChild(“Conditions”).GetComponentsInChildren();

Is it better way that a designer can add and remove these conditions without knowing extra knowledge and concepts?
How can we extend it to contain more generic states for commands too?
for example they are executed in OnTriggerStay or OnCollisionEnter or other sections

:confused:

Well, I guess that depends on what you mean by “better”. Just brainstorming, here are a few alternatives:

  • Make a custom editor that allows designers to build up these conditions with something like a graph or tree.

  • Use something like MiniScript to let designers type in a boolean expression (including whatever functions you define).

  • Scrap the whole idea of designers defining complex conditions; instead just make a little class for each type of interactable item that defines that logic in code, and let designers pick from this library of types.

Your system seems like a decent approach too though (if you really do need that much complexity).

Thank you JoeStrout.
So you say I use the way for simple items with simple conditions and commands and for complex items with hard and complex conditions and commands, make different classes without this design that splits commands from conditions?
or you say throw away completely the approach (conditions commands separation) and make normal classes with different items? like below:

```csharp
**public class CBaseItem:Monobehaviour{

}
public class item1:CBaseItem{
void Start(){}
void Update{
// conditions and commands here
}
void OnTriggerEnter2D(Collider2D _coll){
// conditions and commands here
}
}**
```

Basically, I’m saying, do it however makes sense to you. Just be careful that you’re not making it more complicated than it needs to be.

I wanted to make only one class (CItemScene) in the past way that takes conditions and commands,checks conditions and run commands but it has limits. So it is better to implement different item classes that takes special conditions and commands. Thank you

public class CSimplePickableItem:Monobehaviour{
   CCondition m_playerNotOwnerCondition;
   CCommand m_pickUpCommand;
    void Start(){}
    void Update{
    }
    void OnTriggerEnter2D(Collider2D _coll){
        if(_coll.tag=="Player"){
           //...
           if(m_playerNotOwnerCondition.CheckCondition){
                m_pickUpCommand.Execute();
           }
        }
    }
    }
public class CComplexPickableItem:Monobehaviour{
   CCondition m_playerNotOwnerCondition;
   //etc
   CCommand m_pickUpCommand;
   //etc
    void Start(){}
    void Update{
    }
  void OnTriggerEnter2D(Collider2D _coll){
        if(_coll.tag=="Player"){
           //...
           complex conditions and commands
        }
  }
}

It prevents to duplicate codes too, because we define conditions and commands and use them inside classes.