Animation FAQ

From HEWIKI
Jump to: navigation, search

Contents

Why does an error pop up when an animation is initialized and then works fine afterwords?

The first time an animation loads, if it is not already downloaded, it will not play and throw an error while the Amin is retrieved from the server. So the next time the Amin is requested it is downloaded and plays. This is normal behavior.

If you need the animation to be always ready, then you should mark its sequence +preload. For sequences that are not critical, you can leave -preload and set them to use a fallback sequence (an example would be if you have 50 different character wave animations, you might have the basic one be preloaded and all of the others not but set the fallback for them to be the basic wave sequence).

Is there a way to mark all ASQ preload values to true?

There is no other way to mark all ASQs preload = true other than by editing the ASQ to update it. The AAS has no control over whether the sequences are +preload or not. If you need the animation to be always ready, then you should mark its sequence +preload. For sequences that are not critical, you can leave -preload and set them to use a fallback sequence (an example would be if you have 50 different character wave animations, you might have the basic one be preloaded and all of the others not but set the fallback for them to be the basic wave sequence).

How do I display Scaleform in 3D space?

Like all GUI controls, you can create a billboard node out of a scaleform gui control to place it in the world as a 3d object.

external function CreateBillboardFromGUIControl(control as NodeRef of Class GUIControl) as NodeRef of Class HBNode
external function RemoveBillboardFromGUIControl(control as NodeRef of Class GUIControl, destroyBillboard as Boolean)
external function GetBillboardNodeFromGUIControl(control as NodeRef of Class GUIControl) as NodeRef of Class HBNode
external function GetGUIControlFromBillboardNode(billboard as NodeRef of Class HBNode) as NodeRef of Class GUIControl

Example code can be found in HJ Reference's client script BillboardGUIHandler.

What is a behavior?

Behave commands set the controller's states, which are evaluated during the pre/post anim callbacks. During the pre/post anim callbacks, the controller analyzes its own state, and then makes any gross navigational decisions it must, applies gravity, makes sweep tests, etc and then sets any animation inputs it needs.

What are behave commands?

Behaviors are used to set state on the controller, the controller sets inputs in the animation agent. It is not using your input_movement script to directly modify the inputs of the animation agent, leave that to the controller.

Can you spit out an asq of an animation applied to a specific animation channel (other than AnimAllBody) in Animation Agent?

Within the Animation Agent Script itself, no as the actual sequence is ultimately up to the animation mixer to figure out based on channel priorities, the sequences currently playing, sequences set to play next, etc. You can use the behavior commands Behave commands#Debugging Utilities exposed by system to see into the mixer's decisions....but it is exceptionally spammy.

How do I set up a weapons bone of a rig for a character?

Exporting the character as a dynamic character with the weapon as one of his parts is one way to do this. The other way (and the one we use in Hero's Journey for their weapons) is to instantiate the weapon using a prop bucket (i.e. HSL code Prop bucket) and then have the character "hold" it using a character behavior Character Behave Commands#HOLD that allows you to specify a bone and positional/rotational offset.

How do I implement a chair sitting animation?

Precise maneuvering via animation such as is typically used in conjunction with action marks is definitely tricky. The basics here are right for the local view of the action. First lets talk about the action mark...

Action marks define the point to which you navigate based on a combination of Width, Depth and the DeadZone. In the case of the action mark below, I show two different action marks one with a deadzone of 2.99 (top) and the other with a much smaller DeadZone. The second action mark because of its smaller deadzone will have a larger number of potential points to which the character might navigate based on a calculation of which is closest to where the character is now.

AnimationActionMarkDeadzone.png

When performing extremely precise actions such as sitting in a chair you of course want a very small number of potential points so the top action mark's "mark line" (closer to a mark point) would be better for sitting in a chair than the second one. An additional issue with using the "CHAIR" actionmark is that characters of dramatically different sizes (think gnome vs giant) are doing to have different needs for sitting in a chair that is human sized....the visualization for the CHAIR action mark is based on HJ's characters of approximately 2 meters.

If you are using animation driven motion (as opposed to translation via the controller), you do need to perform a snap when the character reaches the destination. This should be done via the behave command setposition and not the external function because you need the character controller to also be set into a proper state. Then facing is dealt with, and finally you need to sit.

Depending on how you have set up your animation agent, the command to SIT hopefully is playing a Transitional Animation STAND->SITCHAIR and then you probably have a looping animation that is played until you perform another transition for SITCHAIR->STAND. You need to use transitions in your animation agent script so that you always play the appropriate transition when breaking out of "sitting".

Hero's Journey's Agent Looks something like this:

transition BasePosture {
 
  from Idle to Sitting = trSit
  from Turning to Sitting = trSit
  from Moving to Sitting = trSit
 
  from Sitting to Idle = trStand
  from Sitting to Turning = trStand
  from Sitting to Moving = trStand
  from Sitting to Climbing = trClimb
 
  ...etc
}
 
 
// The trSit transitional action handles the transition from standing to a
//   sitting position
action trSit
{
 
  force(1) AnimAllBody
  {
 
    when SitType {
    is Chair:
      anim "Sit_chair"
      change IdleType to SittingChair
    is Ledge:
      anim "Sit_ledge"
      change IdleType to SittingLedge
    is Ground:
      anim "Sit_ground_multi"
      change IdleType to SittingGround
    is GroundLean:
      anim "Sit_ground_multi"
      change IdleType to SittingGround
    }
 
    hold 1
    blend 0.1
    align false
    looping false
    change AlreadyTurning to False
    change CurrentMotion to Idle
    change Attacking to None
    stop
  } 
}
 
// Basic Idle behaviors, controls the animations that will be played when nothing else is happening.
action fnIdle {
  set(1) AnimAllBody
  {
    call fnEvaluateIdleInputs
 
    change AnimationSettingsGroup to Primary      // Groups of Align/Blend/Hold/Looping settings that are used in common
                                                                           //   by many animations
 
    when IdleType {
    is SittingGround:
      anim "idle_sit"
      change AnimationSettingsGroup to Secondary
    is SittingLedge:
      anim "idle_sit"
      change AnimationSettingsGroup to Secondary
    is SittingChair:
      anim "idle_sit"
      change AnimationSettingsGroup to Secondary
    DEFAULT:
      when Emote {
      is None:
        // pass through
      DEFAULT:
        anim str( "emote_", Emote )
        align false
        blend 0.1
        hold .9
        looping false
        change Emote to None
        stop
      }
 
      when BaseMode {
      is Combat:
        anim "combat_idle"
      DEFAULT:
        anim "idle"
      }
    }
 
    when AnimationSettingsGroup {
    is None:
      return
    is Primary:
      align false
      blend 0.1
      hold 0.1 seconds recycle
      looping true
      change SitType to None
      change AllowImpacts to True
    is Secondary:
      align true
      blend 0
      hold 0
      looping true
    }
  }
}

This should get us to the point where the character in the local view is performing a fairly pleasing sitting action. Now it is possible you may wish to make specific tweaks to your game specific Advanced Customizable Character Controller to refine the behavior further to suit your particular needs.

Now we need to talk about what remote clients see....

Remote clients add in an additional level of difficulty and we need to consider how replication works and whether or not that is really appropriate when trying to control movement as precisely as we do with action marks as well as how we communicate state to clients logging in.

Normally, the movement of your character is replicated from your local client to the server and then out to other interested clients because the server has assigned control of reverse replication of specific fields on your controller node. When a remote client receives an incoming movement packet, it attempts to move your character in a manner that within a margin of error mimmics how your character moved on your client. This is complicated of course by the animations your game specific controller chooses to achieve that movement when you use animation driven movement. All of this tells us that it is going to be hard to use the replicated movement to achieve a precise result...which we need for action marks.

So, that means that we want probably want to have each remote client handle the action of sitting directly rather than depending on replication of movement packets so that we have better control over the look of the action. To do this we will want to pass some additional information from our local client for example the STATE of SITTING and the ID of the action mark we are using for the precise navigation required to achieve it. When the server receives the SITTING State change, it will replicate that to interested clients and then you have an option. You can either remove the control of reverse replication for your character so no movement packets are sent...or you have have clients ignore all movement packets while their STATE is SITTING until they receive a STAND state change.

What is a knob?

Knobs Knobs#Knobs are used to influence animation sequence abilities such as tne Multiplexer, Blend2 or Speedblend from HSL. Essentially, a knob acts as a filter which is used by the sequence to determine ultimately which animation file(s) will be played. A knob exists as an internal data structure of the animation agent for a particular character Animation agent and is used by the animation mixer when a sequence is played.

How do I implement blending animations?

There are several options for blending animations:

For the head down/up use case, you would typically use the Blend2 ability to blend between the two animations based on a knob Knobs#Knobs that is set externally via script, console, properties panel using behave commands.

Does HeroEngine support combined animation?

HeroEngine supports the ability to play animations on animation channels that you create by masking off skeleton bones in max/maya. So for example, during the authoring process you might choose to create a mask Attacks(i.e. the Attacks channel) on which you play your combat animations when moving. You can see an example in Hero's Journey's implementation of impact animations on the "Impact" channel when moving so that movement is not interrupted.

The animation agent file (BipedAgent.aas) is located in the repository in the path \Character\Animations\BipedAgent.aas.

Why are my characters experiencing syncing problems?

Ultimately, both of these problems boil down to the storage and communication of state.

The default HeroEngine character controller (HeroEngine_ACCController) is good enough as a starting place to get you going, but it is intended to be replaced by a game specific controller that stores and communicates your game specific states. In v1.21, we moved character introduction from C++ to the highly configurable and flexible replication system allowing control over precisely how state is communicated.

In a broad outline form you will:

You may choose to use the HeroEngine_ACCController as a conceptual basis for your control, but I recommend you not inherit from it because you will want to use your own game specific fields so you can modify enumerations replication parameters and you may simply not need some of the fields included.

The creation of a game specific controller may be complicated depending on the needs of your game.

See:

Advanced Customizable Character Controller
Replication
Class Replication Parameters
Field Replication Parameters
Replication Script Interface
Replication Tutorial

Do I Really Need an NPC for a "Visual Effect"?

On the subject of "birds" or other npcs intended to provide flavor to an area, you may want to consider having these types of what I like to call "visual effect" creatures not actually be NPCs rather using the FX System or custom code generate an instance of an animated asset and fly it around by transforming its position/rotation locally. In HJ, we used particle effects and animated assets to create what appeared to be flocks of birds circling a tall castle to create a very convincing illusion that was very lightweight in turns of processing/memory costs.

This would be an acceptable route to take if "where" a "visual effect" creature is has no important to game play and may be most convincing at a distance.

Of course, if you want your birds to do complicated animations like landing/taking off and so on then the more full featured route of using the animation system for characters would be preferred.

Personal tools
Namespaces
Variants
Actions
Navigation
Toolbox