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 What is proper way to control a player character?(fsm? bt?)

Discussion in 'Scripting' started by Elrendar, Oct 7, 2020.

  1. Elrendar

    Elrendar

    Joined:
    Dec 16, 2017
    Posts:
    2
    Hi. I'm asking for advice about how to control my character. Especially while fsm(or bt?)is running.

    I'm working on my personal project that is a 3D isometric view hack & slash game, like diablo 3.

    I was dealing with dx9(and c++) before, and this is my first project with Unity. (new to c# too)

    I was using simple fsm to controll player character and AIs. It didn't work so good I was new to programming.

    The most difficult part was handling input while the fsm is running on update. The code wasn't look so good.

    This is a sample of my fsm code. (Sorry it's c++)

    Code (CSharp):
    1.  
    2. // declare:
    3.  
    4. class CState_Player_Idle : public CState_Player // <- this is abstract class
    5. {
    6. public:
    7.    virtual           ~CState_Player_Idle() {}
    8. public:
    9.    virtual void   Ready(CCharacter* player);
    10.    virtual void   Update(CCharacter* player);
    11.    virtual void   Exit(CCharacter* player);
    12. private:
    13.    void             Handle_Input(CCharacter* player);
    14. };
    15.  
    16. //implement:
    17.  
    18. void CState_Player_Idle::Ready(CCharacter * player)
    19. {
    20.    player->Setup_Animation(0);
    21.    player->Set_Combat(false);
    22. }
    23.  
    24. void CState_Player_Idle::Update(CCharacter * player) // < invoke this one every frame
    25. {
    26.    Handle_Input(player);
    27.    player->Play_Animation();
    28. }
    29.  
    30. void CState_Player_Idle::Exit(CCharacter * player)
    31. {
    32. }
    33.  
    34. void CState_Player_Idle::Handle_Input(CCharacter * player)
    35. {
    36.    if (Key_Pressing(DIK_W) || Key_Pressing(DIK_A) || Key_Pressing(DIK_S) || Key_Pressing(DIK_D))
    37.    {
    38.        player->Change_State(move_);
    39.    }
    40.    if (Key_Down(DIK_SPACE))
    41.    {
    42.        player->Change_State(combat_);
    43.    }
    44. }
    45.  
    46. // There were more states like move, combat, attack, knockdown, skills, roar(just a animation!), etc.
    47.  
    As you see, I had to make Handle_Input method in every state class I need to handle key input. I wondered if this was the proper way, but I never saw anyone else's code, so I couldn't know.

    On the other hand, I heard about behavior tree when I was googling fsm, and I thought its idea is cool. But I couldn't use it for my dx9 project, because my coding skill wasn't good enough to use it.

    I found some samples on the assetstore, but the codes are so complicated. So I tried to make my own, but I got stuck in handling key input with mecanim.

    Finally, I realize I really really need to study more. Please give me some advice. I would also appreciate it if you tell me about the website or YouTube videos can help me learn more.
     
    Last edited: Oct 7, 2020
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,762
    It does get hairy... one way to help break it down is to process the user input as sort of like a "data flow."

    You can model it as:

    - user inputs lead to a user intention

    - a user intention is judged to be valid or invalid based on state

    - if valid the state is processed and the intent is considered satisfied

    - if a state doesn't care about an intent, it lets it go by to the next processor.

    That way if you are wielding a sword, "attack" is a valid state.

    But if the sword sees "walk left" it just ignores it and passes down to the next.

    Unity also lets you plug lots of behaviors into an object, then have a single behavior that controls which one is enabled right now, very Component-oriented.

    Finally out of all that you want to mimick everything with an actual animator state machine that you setup and drive accordingly.

    Here was some discussion of partitioning logic between code and the animator state machine.

    https://www.gamasutra.com/blogs/JoeStrout/20150807/250646/2D_Animation_Methods_in_Unity.php
     
  3. Elrendar

    Elrendar

    Joined:
    Dec 16, 2017
    Posts:
    2
    Thank you very much. I read your reply and article you linked, but I'm still confused.

    I'm not sure if I understand your word properly.

    If sword(you mean attack state in fsm, right?) ignore my input(walk left), then I have to change state to idle when attack animation is finished, and then idle state can handle input.

    Did I get it right?


    By the way, I also read the article from Gamasutra. It was interesting because the first and second approaches look very similar to what I did in dx9 project.

    But I'm not sure what to get from the article. As author mentioned at the end of the article, I guess it's hard to keep away from Mechanim when working on 3d characters.
     
    Last edited: Oct 8, 2020