Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Handling turn-based actions in steps

Discussion in 'Game Design' started by CliffCoffee, Jul 31, 2017.

  1. CliffCoffee

    CliffCoffee

    Joined:
    Jun 30, 2017
    Posts:
    7
    I have hit a roadblock in implementing an action system into my current project, a turn-based RPG (2d). Naturally, I expect I may be over-engineering it or just not thinking about the concept quite clearly to implement it properly.

    The requirements:
    • During the "process" state, the action(s) the player previously selected for the current unit are called and resolved.
    • Actions occur in serial order - one after another.
    • Actions may have many visual effects that must be applied in steps over time
      (For instance an attack would require the attacker to play an animation, spawn a slashing effect, determine if the attack hits, play an appropriate sound, spawn the hit effect, play the target's damage animation, etc.)
    • Only after all steps are resolved should the process state transition back to the command state where player can select a new unit and give it actions.

    I can think of ways to do this, but not sure what will actually work properly in the end.

    At a glance it seems to make sense to spawn a prefab for the effect that contains an Animation Controller with StateMachineBehavior scripts at various points to fire the effects and process logic. This Effect Manager of sorts would allow the steps to be separated clearly, and for the final state's OnStateExit to mark the effect complete. However the prospect of maintaining Animation Controllers and StateMachineBehavior scripts for every single weapon and spell effect seems to be laborious and error-prone.

    Does this sound crazy? normal? is there a cleaner way that still allows multiple animations and actions to be choreographed?
     
  2. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Well, the obvious alternative is to do it in code with some sort of tweening/sequencing library — either something off-the-shelf, such as DOTween, or by rolling your own.

    In other words, you'd have code for each weapon or spell effect that says: do this, then do that, then wait 0.5 seconds, and then do these two other things, etc. All of these just build a list of little structs that keep track of what's supposed to happen in the sequence. Then you tell it "Go," and some MonoBehaviour runs that works through the list with the specified timing. At the end, it could fire some event or callback to let you know it's done (so you can transition back to the command state).

    It's basically the same thing as using an Animation Controller with state machine behaviors, but possibly easier to code and maintain... more typing, but less dragging and dropping. To me that's a good trade.
     
    Ryiah likes this.
  3. CliffCoffee

    CliffCoffee

    Joined:
    Jun 30, 2017
    Posts:
    7
    Thanks for your reply, JoeStrout.

    The only real trouble I see with using StateMachineBehaviour scripts is that they don't have GetComponent so you have to use animator.GetBehaviors<T> to set references. But that is not the end of the world I suppose.

    To offer some context - I wrote most of this game's functionality (including these sequences) entirely in browser JavaScript and Canvas just to prove to myself I could do it. It was a great learning experience but I wouldn't suggest anyone do that unless they are crazy like me. I was more successful in that than I was previously in Unity (or UE4 for that matter) but coming back to Unity after doing that exercise really put things in perspective for me and made me appreciate what Unity does for you.
     
  4. CliffCoffee

    CliffCoffee

    Joined:
    Jun 30, 2017
    Posts:
    7
    Funny, 2017.1 version introduces Playables API in stable and was released just recently. Particularly AnimationPlayable and ScriptPlayable look promising! I will post my findings.
     
    JoeStrout likes this.
  5. EternalAmbiguity

    EternalAmbiguity

    Joined:
    Dec 27, 2014
    Posts:
    3,144
    Please do, I'm interested in this.
     
  6. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Sounds like a simple nested FSM is the answer. The top level system just waits for the bottom level systems to complete before moving on.
     
    frosted and Ryiah like this.
  7. CliffCoffee

    CliffCoffee

    Joined:
    Jun 30, 2017
    Posts:
    7
    I have played with the Playables. =)

    It seemed to be overcomplicated for what is needed in this case, but I do see potential value. It all made sense and worked but each time I came back to it required quite a bit of familiarization again to make sense of it (and if that happens to me I can see most designers scratching their heads too). It worked, but considering I needed to have many different effect behaviors it added a level of complexity that was not necessary.

    I ended up creating a delegate function on the ability class itself, and making the animation event function just call that delegate. This way many different abilities can be created using the same generic animation event function, but the underlying ability can fire its own behavior.

    Since all abilities use ScriptableObjects to configure their general behaviors and visual/audio effects, the code only needs to be updated for new types of abilities, not individual abilities since they can just be created right in the inspector.
     
    JoeStrout and EternalAmbiguity like this.
  8. Hyblademin

    Hyblademin

    Joined:
    Oct 14, 2013
    Posts:
    725
    More like BT's, maybe?

    I've had luck writing a behavior that accepts enumerated events for various things (move the camera, disable player controls, invoke dialogue, play sounds, create objects) and an editor script that creates a UI for adding events into a linear sequence, which will then be executed in order. There are also events for waiting for a number of seconds or waiting for a callback before continuing. The intended purpose was for a cutscene designing system, but it was easily generalizable to anything that needed to run in a sequence.

    I feel this could easily enough be adapted to something more dynamic, where logic is used to populate the events, then they are executed at the appropriate time.
     
  9. HolBol

    HolBol

    Joined:
    Feb 9, 2010
    Posts:
    2,887
    Use some sort of simple state machine. Break up each round into phases in the code. Expose all the values you need to write the dialogue and animation controllers on top of the battle system so that you can interface between them.
     
  10. CliffCoffee

    CliffCoffee

    Joined:
    Jun 30, 2017
    Posts:
    7
    Good points all around.

    I am revisiting this after some time away working on another project. I will be posting updates within the next week