Related Discussions
...
8 days later

Has anyone experimented with using an FSM tool like NodeCanvas?

I just spent tonight putting together an FSM. As note.. I'm a programmer and hate visual tools like Playmaker, but lately I've began coordinating with level designers and it has made me appreciate not having to explain every single line of code I write.

What I'm curious about is... how does everyone currently code their animation controllers? With a basic enum for the state and SetAnimation method if a change is detected frame to frame? Unsure if that is more complicated than what I came up with, but the below seems to be working out well.

The EntityMovement script controls variables in the blackboard like movement speed, grounded, jumping, climbing, "triggers" for attacks where I set a boolean back to false the state it is used in and other things like getting hit.

I use one simple associated NodeCanvas task for this on each node.

The reasoning for the complex attack states is because some animations will flow into others. Attack 1 can lead to Attack 2 if you hit the attack button during the "last 25%" of Attack 1, so I detect this by always writing the normalized time of every animation to a variable and allow the boolean MeleeAttack to be turned on if within that last section or if completely not attacking at all.

All of the combat logic can also be controlled in here since OnEnter and OnExit can change booleans directly. If you enter a GetHit status you can set an input lock out until the animation completes instead of constantly checking for what animation is playing on specific tracks and running all your logic in code.

using System.Collections.Generic;
using NodeCanvas.Framework;
using ParadoxNotion.Design;
using UnityEngine;
using Spine.Unity;

namespace NodeCanvas.Tasks.Actions
{
    [Category("Picklefeet")]
    public class PlayAnimationSpine : ActionTask<Transform>
    {
        private SkeletonAnimation skeletonAnimation;
        private Spine.AnimationState spineAnimationState;
        private Spine.TrackEntry trackEntry;

    private Blackboard bb;

    [RequiredField]
    public string animationClip;
    [SliderField(0, 4)]
    public int layer = 0;
    public bool loop = false;

    public float exitTime = .85f;
    private float desiredExitTime;

    public float timeScale = 1f;

    public BlendType blendType = BlendType.Set;
    public enum BlendType
    {
        Set=1,
        Add=2,
    }

    //0% means no events from the "from" anim will fire, 100% means mix all events from the "from" anim during transition
    public float lastTrackEventThreshold = 1f;

    protected override string info
    {
        get { return "Anim " + animationClip.ToString(); }
    }

    protected override string OnInit()
    {
        if (skeletonAnimation == null)
        {
            skeletonAnimation = agent.GetComponentInChildren<SkeletonAnimation>();
            spineAnimationState = skeletonAnimation.state;
            bb = agent.GetComponent<Entity>().bbAnimation;
        }

        return null;
    }

    protected override void OnExecute()
    {
        if (blendType == BlendType.Set)
        {
            trackEntry = spineAnimationState.SetAnimation(layer, animationClip, loop);
        }
        else if (blendType == BlendType.Add)
        {
            trackEntry = spineAnimationState.AddAnimation(layer, animationClip, loop, 0f);
        }

        trackEntry.TimeScale = timeScale;

        //new code for stopping event mixing from the previous animation
        if (trackEntry.mixingFrom != null) 
        {
            trackEntry.mixingFrom.eventThreshold = lastTrackEventThreshold;
        }

        //set the desired exit time to x% into the animation
        desiredExitTime = trackEntry.Animation.Duration * exitTime;
    }

    protected override void OnUpdate()
    {
        //if this animation doesn't loop, immediately end and transition out when completed
        if (!loop && trackEntry.TrackTime >= desiredExitTime)
        {
            EndAction(true);
        }
    }

}
}

23 May 2016, 21:42


Really surprised no one has responded to this. The usage of NodeCanvas's FSM tool has been paramount to our game development. The workflow from the animator has changed a ton. I can test changing animation speed on the fly instantly during runtime and click GetHit booleans and triggers to see stuff flow and happen live without having to set up OnGUI nonsense or click the inspector for each animation. While that does work it doesn't let you see all the blending. You can create nodes at runtime and connect them... set up all your transition requirements like IsJumping, etc etc...

I can't imagine coding this all out now like I assume most people do.

3 months later

We're just getting our feet wet here, but we're using plain mecanim, with some extra scripts attached to:

• not show the bind pose frame, but do an update on frame 0 with the first animation
• switch to a clips at random, from one node
• resume a clip where it left off after going out- and back to it
• some random sprite tinting

Visually and seeing that variables panel, I'd instantly beg our developers to start using Nodecanvas, but I work at a plugin-averse company, do you have more positive experiences I can use to sell them on it?

It does look really cool. I wish I had time to write games! Stupid Spine! :p

Also just started using NodeCanvas (and Spine of course). Wouldn't want to do all that stuff in code, even though I also implemented a small FSM for really simple stuff.
NodeCanvas seems to be really solid, all the source code is there as well. Also it's really flexible since you can have nested behaviour tress in your FSM (and vice versa). I think that combination is quite powerful.
It also is really easy to write your own actions that you can then use in the FSMs/BTs. Haven't come across another plugin that does the same and isn't bloated with all kinds of other features, like path finding etc.

Can recommend NodeCanvas!

7 days later
nimbling wrote

We're just getting our feet wet here, but we're using plain mecanim, with some extra scripts attached to:

• not show the bind pose frame, but do an update on frame 0 with the first animation
• switch to a clips at random, from one node
• resume a clip where it left off after going out- and back to it
• some random sprite tinting

Visually and seeing that variables panel, I'd instantly beg our developers to start using Nodecanvas, but I work at a plugin-averse company, do you have more positive experiences I can use to sell them on it?

Spine most likely will always work much better using its native runtime instead of through Mecanim. By using SpineAnimation instead of SpineAnimator you also gain reliable access to events baked into your animations. Mixing animations is stupid easy with nested FSMs and the visual transitions. It's a very simple move to a Nodecanvas FSM because you're still working with the bool/int/float params as you see in the "Blackboard" just like a Mecanim tree. There's OnEnter/Update/Exit per state callbacks to hook into and it's just everything we could possibly have needed to make Spine work super easily. I no longer have to deal with unity animation hierarchies and dragging clips all over the place or using override controllers for all our different monsters with differently timed animations with the same name. One monster FSM controls all our monsters in game through shared logic.

All your above examples would be easily achievable in an FSM tree. You can write methods in a c# class and simply tie the node directly into the method to fire it once or until success etc every frame. It took me all of 6 hours or so to completely ditch Mecanim and go with a Nodecanvas FSM and our main character has about 25 animations and complex "depending what weapon is equipped" logic for Idle/Walk/Attacks etc.

Another really cool feature I just started using is the ability to capture an event that gets disposed after consumed by the Behavior Tree. You can send something like a "Base Destroyed!!!" event to all AI trees in the area and if configured to consume it they can run some custom logic and then it's used and doesn't have to be a bool you set false manually afterwards.

5 days later

@Majicpanda (all)

Really appreciate you sharing your thoughts on Integration with NodeCanvas. From the limited video tutorials I've found on this Unity asset it 'sounds perfect' + Author seems very active, helpful + healthy product/updates/community. It certainly seemed appealing as a visual artist/spine animator, product manager/non programmer ('trying' to manage quick iteration cycles with programmers/stakeholders and creative quality!)

FYI: I'm just starting to evaluate possible approaches visual editing tool/State/behaviours/manager for use between Unity and spine. Whilst also trying to read reviews/their forums/documentation in the attempt to find a tool which appealed to both designer and programmers (e.g. for real use in production projects/'useful outputs favoured by programming teams' - aka avoiding some more overly simplified unity visual coding tools - mentioning no names!)

So your views/positive experience are really a good swaying factor for NodeCanvas. Tooling and workflows between Engineers and VFX teams are No.1 starting point for me in any healthy project. Hence, I will study this post + your 'Enemy' Asset reference in detail this evening (once I have powered up with some brain food). Really great timing, as I was about to wade into NodeCanvas head first with zero experience. Thanks for sharing!

As a complete 'newbie' to Unity, currently in '48 hour information overload';
I figured I would ?maybe? dig in/fill some knowledge gaps by studying (also: see 'goals' below)

  • Spine-Unity Examples: 'Basic platformer' possibly 'Ragdoll' (SUPER cool by the way)
  • Background reading on 'Mecanim/Unity Animation System/FSM??'
  • See recommendations here within communities favoured Spine approaches.
  • Check if NodeCanvas is viable way forward with Spine

BTW: Nodecanvas looked like a possible candidate for what Im as a designer is terming 'Spine > animation style controller' in Unity. (e.g. controlling logic, switching between animation states within simple test game; collision detection - falling, hit ground). Wasn't sure if I would be swimming up stream/alone, trying to add NodeCanvas in the mix.

Caveat/background context[off topic]:

  • I've literally installed Unity for the first time this weekend. (previously ran projects Starling/SpriteKit > Spine) + had teams extend Unofficial SPINE/heavily optimise use with SWIFT SpriteKit (plan on posting back updates if helpful to others)
  • The big +1 was the integration between official Spine runtimes and Unity/community backing. Hence it seemed a no brainer to have a poke around.
  • The +10 point also was the volume of posts/progressions spanning the last 1.5 years . (BIG thanks to Mitch, Pharan, ToddRivers, Nate/Søren/et al - for sharing your outputs/best practices)
  • In summary: I've tried to wade through anything I could find from youtube videos, forum posts/getting started/github guides and spine-unity project examples.
  • Your efforts are REALLY really appreciated in helping newbies/designers wrap their head around things from different perspectives.

Unity playground project
https://www.dropbox.com/s/32u4v88zk5eixmb/spine-unity-testProject-001.mp4?dl=0

  • I've jumped in headfirst to produce a playground project over the weekend, poking around Unity live sessions 2d physics hat/animation examples.
  • I was initially trying to focus/understand Unity's Native features/artwork>workflows with couple of tests using; Meshes, 2d physics/colliders, particles, camera tracking GUI/BTN/Layout mixed in with testing of 3rd party solutions 'video texture' style
  • Whilst jumping the gun: to get a feel of Unity's patterns/architecture 'Entities and components' against alternatives Entitas-CSharp and DI solutions (Zenject)
  • Hence very impressed what I've been able to hack together (given I still doing tutorials on 'operators' and 'arrays' erggg ( designers 'trying to be coder' down the line ;-)
  • The above REF video is simply a screen record of a useless/messy 'single scene' Unity playground of img assets with a single spine object/animation state - thanks to Raptor/Spineboy!
  • (Currently #Failed on exporting own spine project for use with unity - will try again reading docs carefully)

Back on topic/point ;-) (NodeCanvas/Other)

  • next up, I was looking to replace some elements in the scene to test switching between two spine states, hence looking at possibly options/best practices between Unity and Spine (for designers!).
  • Node Canvas was again appealing given - Given to date I've only botched my way through a basic tutorial in SWIFT/SpriteKit to understand their state machine example project/code (erg 2) so ANY recommended 'Unity' visual'ish solution looks VERY appealing!

Example goals for Spine Unity state test/example video
(e.g. NodeCanvas? - other solutions? hence checking communities views before possibly buying/failing quickly.)

  • Raptor/spineBoy falls down within 2d gravity environment (like current scene)
  • Lands on cube: hit collision between Spine character and cube/box collider?Event fires?
  • Switches Character/State from falling to grounded/breathing
  • Jump/forces applied - e.g. test switchable loop on this logic.
Majicpanda wrote

I no longer have to deal with unity animation hierarchies and dragging clips all over the place or using override controllers for all our different monsters with differently timed animations with the same name. One monster FSM controls all our monsters in game through shared logic.

  • This 'sounded nice' to a designer/avoiding possible future pitfalls.
  • I'd figured I would be swimming up stream, trying to get Spine > Unity > NodeCanvas (working together) however great to hear others already using with Spine.

Hope my dyslexic rambling writings/best efforts to shout out 'I'm a newbie' weren't too painful, given I'm dipping my toes into Unity and some form of coding for the first'ish time! (Hence, help guidance, example project, articles always welcomed to point me in the right direction!)

thanks again in advance!

PS: If anyone else is trying to look at similar tests - happy to fail together - share understandings, examples back to the community.

7 months later

@Majicpanda Thank you SO much. Not only did you introduce me to NodeCanvas(which I as a professional software engineer love 100 times more than PlayMaker, which I have struggled to use as a programmer in the past), you showed me a beautiful way to create a re-usable animation graph. This is a GREAT method. Thanks again!

4 years later

I wonder if it is possible to show animations as a drop down list instead of a simple string field?

Mentioning just in case:
If you (or anyone) find(s) the respective member variable in code you could check if adding the property attribute [SpineAnimation] before it provides the drop down list instead of a string field. E.g. [SpineAnimation] public string animationName;.