๐Ÿงพ
FPS Animation Framework
  • ๐Ÿ‘‹Welcome!
  • Workflow
    • ๐ŸฆพCharacter Rig
    • ๐Ÿ”ŒComponents
    • ๐Ÿ”ธProfiles and Layers
    • ๐Ÿ”—Linking
    • โž•Integration
    • โ–ถ๏ธPlaying Animations
    • ๐Ÿ’ปExtending the System
  • Demo Project
    • โœจResources
    • ๐ŸŽฎController
    • ๐Ÿ”ซWeapons and Items
    • โž•Attachment System
  • Fundamentals
    • ๐ŸฆพRig
    • โš™๏ธFramework Architecture
    • ๐Ÿ“‘Animator Profiles
    • ๐Ÿ“œAnimator Layer
    • ๐ŸŽฎInput System
    • ๐Ÿ”ถAnimator Layers
      • Weapon Layer General
      • Additive Layer
      • Ads Layer
      • Attach Hand Layer
      • Collision Layer
      • IK Layer
      • IK Motion Layer
      • Look Layer
      • Pose Offset Layer
      • Pose Sampler Layer
      • Sway Layer
      • View Layer
      • Blending Layer
      • Turn Layer
    • ๐Ÿ“šNew Animation Library
    • โš’๏ธTools
  • Recoil System
    • ๐Ÿ”ซRecoil Animation
    • ใ€ฝ๏ธRecoil Pattern
    • ๐Ÿ“นCamera Shake
  • Troubleshooting
    • โš ๏ธInitialization Warnings
    • โš ๏ธCan't Look Around
    • โš ๏ธWeapon Positioning
    • โš ๏ธWeapon is not moving
  • โš ๏ธAiming doesn't work
  • โš ๏ธTwisted feet when looking left/right
  • ๐ŸŒŒMisc
    • ๐Ÿ“œChangelog
      • 4.7.0 Update
Powered by GitBook
On this page
  • Overview
  • Example
  1. Workflow

Extending the System

In this section you will learn how to create custom animation modules.

PreviousPlaying AnimationsNextResources

Last updated 5 months ago

Overview

A procedural animation feature consists of 2 entities:

  • FPSAnimatorLayerSettings: a Scriptable Object that contains all the data.

  • IAnimationLayerJob: a struct that executes custom animation logic.

Tip: the framework uses the Animation Job System, which ensures solid performance even with a large number of characters.

If you open up the source code of the framework, you will notice that every layer has its own folder with 2 .cs files:

FPSAnimatorLayerSettings class is responsible not just for containing the data, but for instantiating the IAnimationLayerJob as well:

AdditiveLayerSettings.cs
public class AdditiveLayerSettings : WeaponLayerSettings
{
    ...
    public override IAnimationLayerJob CreateAnimationJob()
    {
        return new AdditiveLayerJob();
    }
}

CreateAnimationJob() method must return a new instance of the desired IAnimationLayerJob-type. When you link a new Animator Profile, the system iterates over all animation features (Layer Settings) and then invokes the CreateAnimationJob() method to create the Layer State.

Example

First, create a new FPSAnimatorLayerSettings-derived class for data, and IAnimationLayerJob-implemented struct:

YourFeatureLayerSettings.cs
public class YourFeatureLayerSettings : FPSAnimatorLayerSettings
{
    //Define your settings here, including the KRigElements.
    public KRigElement myRigElement;

    public override IAnimationLayerJob CreateAnimationJob()
    {
        return new YourAnimationLayerJob();
    }
    
#if UNITY_EDITOR
    public override void OnRigUpdated()
    {
        base.OnRigUpdated();
        
        // (!) Always update KRigElements here.
        // Called when a rig asset is updated/changed.
        UpdateRigElement(ref myRigElement);
    }
#endif
}
YourAnimationLayerJob.cs
public struct YourAnimationLayerJob
{
    private YourFeatureLayerSettings _settings;
    private LayerJobData _jobData;
    private TransformStreamHandle _yourBoneHandle;
        
    // Use this method for custom animation logic.
    public void ProcessAnimation(AnimationStream stream)
    {
    }
    
    // Use this for modifying root motion.
    public void ProcessRootMotion(AnimationStream stream)
    {
    }
    
    // This method is called when a new profile is linked.
    public void Initialize(LayerJobData newJobData, FPSAnimatorLayerSettings settings)
    {
        _settings = (AdditiveLayerSettings) settings;
        _jobData = newJobData;
        
        Transform bone = newJobData.rigComponent.GetRigTransform(settings.myRigElement);
        _yourBoneHandle = newJobData.animator.BindStreamTransform(bone);
    }
    
    public AnimationScriptPlayable CreatePlayable(PlayableGraph graph)
    {
        return AnimationScriptPlayable.Create(graph, this);
    }
    
    // Make sure to return a reference to the active asset.
    // It will be used by the FPSBoneController to compute a layer weight.
    public FPSAnimatorLayerSettings GetSettingAsset()
    {
        return _settings;
    }
    
    // Use this method to update job data when a layer is linked.
    public void OnLayerLinked(FPSAnimatorLayerSettings newSettings)
    {
    }
    
    // Use this method when a new weapon or item is equipped.
    public void UpdateEntity(FPSAnimatorEntity newEntity)
    {
    }
    
    // Use this method before the main update to gather input data.
    public void OnPreGameThreadUpdate()
    {
    }
    
    // Use this method to update playable data and gather game thread data.
    public void UpdatePlayableJobData(AnimationScriptPlayable playable, float weight)
    {
        _jobData.weight = weight;
        playable.SetJobData(this);
    }
    
    // Use this method when a finalized pose is required.
    public void LateUpdate()
    {
    }
    
    // Use this method to dispose data manually.
    public void Destroy()
    {
    }
}

In the next chapter, we will learn how to work with the demo project.

๐Ÿ’ป
AdditiveLayer example.