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. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

Strategy pattern for Monos

Discussion in 'Scripting' started by mahdiii, Dec 18, 2018.

  1. mahdiii

    mahdiii

    Joined:
    Oct 30, 2014
    Posts:
    853
    Hi. I would like to use strategy design pattern to change behaviour in runtime.
    Suppose I have a camera with different behaviours (fixed, following, etc) or I have some NPCs that can change their behaviours.

    What is your approach?
    1- Use state machine
    2- Use AddComponent and RemoveComponent to add new behaviour and remove the old one. (Strategy pattern)
    3- Define children (Hierarchy) for each behaviour and use SetActive to activate and deactivate behaviours.
    4- Define a controller to change the behaviour. (switch case between behaviours, etc)
    5- Other approaches


    Do we rarely use strategy pattern for monos ?
    When and where do we use strategy pattern (instead of state machine for example) and it is suitable? Can you give me an example? Thanks
     
  2. Lurking-Ninja

    Lurking-Ninja

    Joined:
    Jan 20, 2015
    Posts:
    9,900
    I have one Camera behaviour, which implements the basics and the common things (movement, utility methods, etc). I also have a couple of ScriptableObjects which handles the different behaviours like follow or freelook, etc and I just plug in to the behaviour the proper one. These are considered assets, so they can be reused, although they can be assigned even in the inspector.

    I don't like creating/destroying objects in-game. It's usually too expensive. Since I usually don't work with mobiles or other extremely restrictive environment, the memory usage is not a concern (which means I can keep them in memory).
     
    mahdiii likes this.
  3. mahdiii

    mahdiii

    Joined:
    Oct 30, 2014
    Posts:
    853
    Thank you but you did not say how you change the behaviour in runtime.
    You have an array of SOs in CameraController and change the behaviour like below?
    or directly refer to special SO in other monos and call change method of cameraController with the behaviour?

    Code (CSharp):
    1. public class CameraController:MonoBehaviour{
    2.    [SerializeField] private CameraSo[] _cameraSos;
    3.    private CameraType _cameraType;
    4.  
    5.    // or use current camera reference
    6.    private CameraSo _cameraSo;
    7.  
    8.    public void ChangeBehaviour(CameraType cameraType{
    9.       _cameraType=cameraType;
    10.  
    11.    }
    12.     public void ChangeBehaviour(CameraSo camera){
    13.       _cameraSo=camera;
    14.    }
    15.    private void Update(){
    16.        _cameraSos[(int)_cameraType].Act();
    17.        _cameraSo.Act();
    18.    }
    19. }
    Code (CSharp):
    1. public class SomeClassChangeCameraBehaviour:MonoBehaviour{
    2.    [SerializeField] private CameraController _cameraController;
    3.    [SerializeField] private CameraSo _newCameraBehaviour;
    4.     public void Func(){
    5.        // change cameraBehaviour
    6.        _cameraController.ChangeBehaviour(_newCameraBehaviour);
    7.    }
    8. }
    Did you not use state machines?
    In order to switch between guns, what is your suggestion?
    Create different children for each gun and switch between them using setactive?
     
    Last edited: Dec 19, 2018
  4. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,186
    I do a lot of what @LurkingNinjaDev does, but using plain classes instead. That can both be used for state machines, and just for other instances where you need to swap how a MonoBehaviour is doing it's thing.

    This could be done though just selecting which method to run, but having an abstract base class for the strategy, and the actual strategies in a different file often helps readability.
     
    mahdiii likes this.
  5. mahdiii

    mahdiii

    Joined:
    Oct 30, 2014
    Posts:
    853
    Thank you. I say that I would like to change the behaviour in runtime.
    You don't use enum or SO types to determine new behaviour?
    Instead, you use new behaviour object in other class and set new camera behaviour in cameraController?
    Code (CSharp):
    1. public class SomeClass:MonoBehaviour{
    2.    [SerializeField]
    3.    private BaseCamera _camera;
    4.    public void OnTriggerEnter(Collider2d coll){
    5.       if(someCondition){
    6.            CameraController.Set(_camera);  //new behaviour
    7.           //or use type
    8.           CameraController.Set(_cameraType);  //new behaviour type
    9.        }
    10.    }
    11. }
    So you use plain or SO classes to prevent adding and removing components (monos). It is perfect.
     
    Last edited: Dec 19, 2018
  6. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    Prop tip, look into the Liskov substitution principle, it's the L in SOLID. It really explains how and why you should be using this pattern