Search Unity

Animation advice for action RPG (multiple weapons)

Discussion in 'Animation' started by maky13, Apr 6, 2019.

  1. maky13

    maky13

    Joined:
    Jul 16, 2018
    Posts:
    7
    I want to ask for advice regarding best practices with animations.

    First, some info: I am developing an action-RPG game (Diablo style); very small indie team, nobody has any experience with animations. Our hope is to be able to work with paid contractors for the animations, and because of this, before spending money left and right, I want to understand good principles and have a solid plan.

    What we want: animations to cover combat scenarios (idle, run, various attacks, various casts) and slightly different visuals for different groups of weapons (think 2x 1-handers vs 2-hander) for each of these scenarios.

    So far we use an animator controller with substates for each of the weapon groups. Inside each weapon-group substate are all the animations for that given weapon group: Idle, Run, Attack1, Attack2, Attack3 and so on. Furthermore, each of these animations has a transition from AnyState (each with their own trigger).

    My questions:
    1. Is this a good setup? I remember reading that having a lot of AnyState transitions is not good practice.

    2. Looking at same scenario for different weapon groups - let's take for example Run. I want this to look similar between 2-hander and 2x 1-handers: only the upper body (hands) are changing slightly. I understand that this can also be done from Layers, AvatarMasks and IK but I don't understand how it's meant to work.
    Right now we have different placeholder animations for each, so our options are (let's assume 6 weapon groups):
    - Commission 6 completely different animations for each scenario; but this is overspending the budget.
    - Commission 1 animation for each scenario then attempt to tweak it outside Unity in order to produce 6 slightly different ones; I am hoping that this will result in less cost, but the result in Unity is the same.
    - Commission 1 animation for each scenario, then use Mecanim magic inside Unity to adjust it for each weapon group. This part I have no idea how to approach, and is one of the main things I am asking advice on.

    3. Animation events and combat: I want to line up the moment when the damage occurs with a specific fixed time in the animation. I can calculate this in the combat action's script using the fixed time threshold, the animation base duration and the animator speed OR I can put an event in the animation. What is the preferred approach here?
     
  2. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    For starters you should find some free stuff on the Asset Store that roughly does what you want so you can actually set things up and test your approach.

    No, that's the mindless brute force approach. It will work, but it's never going to give you an effective workflow. It's also very inefficient because every animation will always need to be loaded and every character will have states and transitions wasting RAM and processing for every weapon group in your game.

    The official recommended way to do it is with AnimatorOverrideControllers which let you substitute the clips used by existing states at runtime. So you would have only one sub state machine for "Attacks" or something, and just override the clips based on your current weapon. Note that for some baffling reason they implemented it to override based on clip name, not state name. So you can't just have a state called "Attack 1" with no clip, you need to give it a dummy clip with a unique name and override that name.

    I don't have any real experience with AnimatorOverrideControllers though since I created a plugin called Animancer (link in my signature) which gives your scripts direct control over the animations instead of using AnimatorControllers. You could just give your Weapon script an AnimationClip field for each animation you want - idle, walk, an array of clips for attack combos, etc. Then when you attack you can just call something like Play(currentWeapon.attack) to use the attack animation of whatever weapon you currently have equipped.

    You need to find tutorials and experiment with those things then because they are pretty important for setting up complex character animations. I have a bit of an explanation of layers in the Animancer Documentation which might help you understand a little better. The general concepts are the same as Mecanim, but the specifics of the example are very different because Mecanim doesn't let you control things in a script like that, it all needs to be done manually in the Animator window. I'm currently working on better explanations and examples for the next version of Animancer, but it's probably still a month or two away.

    I don't particularly like the way Animation Events are so weakly tied to an arbitrary function name, but I've never been able to come up with a better approach. You just can't beat the ability to preview the exact pose of the model as you adjust the event time.

    A useful trick I've found is to make a ScriptableObject type called HitData or something with specific details about the hit which you give the event so it can pass that into the function it calls. That way you can control things per hit rather than per weapon like damage type, damage multiplier, knockback, and even determine which weapon is performing each hit when dual wielding. For example, rather than all swords dealing slashing damage, a sword combo might have some slashing and some piercing attacks, or a special attack might consist of a bash that deals little damage with a bit of knockback then engulfs the weapon in flames and deals fire damage with the main attack, all in a single animation.
     
    anycolourulike likes this.
  3. subliminole

    subliminole

    Joined:
    Apr 26, 2016
    Posts:
    8
    Hi Maky13,

    There are a few good points in SilentSin's reply so i'll add a little to what they say that is more setup to give you a better plan of action.

    Work out how many stages a single weapon will need, then apply that to each weapon. Once you have the stages a weapon needs for an attack, you can block it out in the animator. Then using the animation override controller you substitute each stage with the correct weapon animation. Its pretty easy to get working, i created stub animations that are named for each state to make them easier to find in the override controller. The planning is important as it will dictate your animator setup as well as the breakdown of animations needed.

    I have only watched a handful of videos from UNITE to get an idea of what others suppose is good animator setup, but i have had success with the "Hub/Spoke" method from the firewatch guys.

    As for the animation events they are useful for certain things that need to be tied to the animation, but they are hard to track when there is an issue. One method would be to use colliders that enable/disable based on animation states. You can tie them into one/many of the above mentioned parts.

    Example: A sword swing animation broken down into five parts:
    Windup -> StartSwing -> MidSwing -> EndSwing -> Recover

    You turn on the collider during MidSwing, doing so through the state machine in the animator with behaviours or use an underlying state machine in your code to do that. You could also use animation events to do this, but the behaviours or code FSM will be easier to test and debug.

    With this breakdown, it means you can also branch your animations at each specific point. If you wanted to start the attack as a swing, but have the player use a button press to change the end, you just branch the end to another state, so the end plays a secondary animation, then plays the recover for the secondary animation.

    Hope that gives you some ideas.
     
    anycolourulike likes this.
  4. maky13

    maky13

    Joined:
    Jul 16, 2018
    Posts:
    7
    Thank you both for your advice!
    I think I'll need to do some more reading on the matter, as it's all very fuzzy to me right now. I'll probably start with the AnimatorOverrideController approach, because I want to keep it simple for now.