2
\$\begingroup\$

I've been looking around for a while trying to figure out how to play simple animations with Unity via ONLY C# script, with no drag-and-drop involved. So far I've found various tutorials explaining how to manually set up a animation controller for each object, then manually select each animation state and manually create a transition then manually set the transition length to the most minimum possible etc...

I was wondering if there's a simple way to just do something like...

gameObject.playAnimation(
    "stand still /* which would be the name of the action state created in blender or other animation software*/", 
    "loop");

...WITHOUT creating an animation controller manually at all, I haven't been able to find any resource to do this simple thing yet.

\$\endgroup\$
  • 1
    \$\begingroup\$ Have you found out a way to solve your problem? \$\endgroup\$ – Sriram Nov 6 '19 at 15:23
  • \$\begingroup\$ @Sriram mainly just using the almost deprecated version of the animation playing, the new GLTF unity extension uses it \$\endgroup\$ – bluejayke Nov 17 '19 at 4:31
3
+25
\$\begingroup\$

Have a look at different approach on Animation using "SimpleAnimation" via new Unity's Playable system.

Introducing the Simple Animation Component (Unity Blog)

enter image description here

Under the hood it hacks the way using animator to play animation while controlling clip and state name from Playables, using new API set UnityEngine.Playables.AnimationPlayableUtilities

But now you can add states easier by script since you are dealing with playables not RuntimeAnimatorController and their messy state system. This is how it looks like when you use it on your end:

// Assumes following variables
SimpleAnimation m_CustomAnimationPlayable; // Via inspector or added on runtime
AnimationClip clip, clip2; // Via inspector or other mean

// Example on creating
m_CustomAnimationPlayable.AddState( clip, "run" );
m_CustomAnimationPlayable.AddState( clip2, "attack" );

// Example on playing
m_CustomAnimationPlayable.Play( "run" );
m_CustomAnimationPlayable.PlayQueued( "run", QueueMode );
m_CustomAnimationPlayable.CrossFade( "run", 1.0f ); // crossfade length

It need quite a bit of initial setup but this official github will provide most boilerplate code for you:

Official Unity Git Hub for SimpleAnimation

Here is outline of setting up

  • You still need pre-constructed Animator in Unity editor but it could be almost blank or most simple one. This allows you to set other useful field in Animator such as avatar setup.
  • Add "SimpleAnimation" component to the game object that has animator installed.
  • Call SimpleAnimation.AddState( clip, name ) to add your own state. You don't have to even define transition. Of course, you need your own way to provide list of AnimationClip to use, it could be drag n drop field in your component or ScriptableObject contains animation database of some kind. Or if you want totally "no-drag-drop", your solution would limit to Resources API and alike. (Refer to @Phillips answer)
  • Play any state or crossfade using SimpleAnimationPlay( statename );

Key point VS legacy Animation component

  • ⌾ Not require marking AnimationClip as Legacy.
  • ⌾ You can use Animator (Mechanim) important features such as Avatar (bone re-targetting), and possibly (I'm not sure) root motion.
  • △ Code amount to setup is around the same as using Legacy Animation.

Be discreet on Resources folder (!!)

  • Resources API has been a good accessible way for loading thing on runtime.
  • BUT Resource folder incurs memory and build performance. For best practice, use it with discreet. Do not dump everything there.
  • Further in-depth read: Asset Bundles vs. Resources: A Memory Showdown
  • Further in-depth read: Assets, Resources and AssetBundles
  • What is worse than Unity's own best practice explicitly said Don't use it.?

There is also AnimatorOverrideController

Keep in mind that there is also another approach AnimatorOverrideController, which is also possible to do on script runtime level. But this is leaning more toward scenario such as having several actors with exactly same state machine but with different AnimationClip override for each state.

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ That's the current way to do it (maybe not with that basic Unity example, though). And Playables are customizable as hell. \$\endgroup\$ – loptrinho Mar 21 at 16:45
  • \$\begingroup\$ where are clip and clip2 defined? \$\endgroup\$ – bluejayke Mar 25 at 19:32
  • \$\begingroup\$ Of course, you need your own way to provide list of AnimationClip to use, it could be drag n drop field in your component or ScriptableObject of some kind. (I will also add these message to answer content) \$\endgroup\$ – Wappenull Mar 26 at 8:02
  • \$\begingroup\$ ADD: Okay, you specified that no "drag-and-drop involved". My bad, but I will leave answer as it is for future reader. For your case on no-drag-drop policy, for starter refer to @Philipp 's answers. You could load resources such as AnimationClip or ScriptableObject from Resources API, all the rest of drill are the same. \$\endgroup\$ – Wappenull Mar 26 at 8:14
1
\$\begingroup\$

I would recommend using an animation controller if you will ever need to blend animations or do any kind of complicated state. If you don't want transitions, you don't have to add them, just call Animator.Play("state_name").

But, if you just want a simple way to play single animation clips, you might be interested in this blog. Unity created that exact component, and you can grab it from GitHub.

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ Hi U;m not exactly sure what :simple animation clips" is different than just playing an animation (AND transiting it to any other) but I jut want to make my point again: I have several models, each with compltely different animation Action sequences in blender, and when imprting to unity, I don't want to use the UI at ALL in any way, everything has to be done with only code, so I'm not entirely sure if this answers the question, but: How do I simply play any animation AND transition any animation to any other animation, just with only the model data, without usign unities UI at all? \$\endgroup\$ – bluejayke Oct 15 '18 at 0:24
  • \$\begingroup\$ and regarding the first part of the answer again, I'm not trying to play animation "states" Im just trying to play the built in animation from the model itself, and I don't want to manually make any "states"a t all so IDK if theres a way to generate all states with C# \$\endgroup\$ – bluejayke Oct 15 '18 at 0:25
  • \$\begingroup\$ If you expand your imported blend file, you will see meshes and animations imported as separate assets. Your MeshRenderer doesn't know about animation data, and your animation data doesn't know about your mesh, so what you are trying to do does not make much sense within the context of Unity. Try learning Unity's animation system, It will only take a few minutes to set up an animation controller once you are used to the system. Just drag and drop your animation clips onto the controller to generate states. \$\endgroup\$ – Kokkivos Oct 15 '18 at 20:48
  • 1
    \$\begingroup\$ @Kokkvios thanks, I hear what your saying "Unitys' animation system is not hhard, just use it!" thanks, but lets say, theoretically, I had 1000 different models, each model has different animation data set up completely differently in blender lets say, and when I import those models into unity, I just want to import them all at once, and simply call a bit of script that says "model.PlayAnimation('walk', 'loop')" or something, WITHOUT any prior setup. Just think practically: the same proble could be if you're loading in the models from a romate server where yuo cAN"t manually drag things!? \$\endgroup\$ – bluejayke Oct 16 '18 at 4:58
  • 1
    \$\begingroup\$ @bluejayke I don't think there's anything to be gained by relitigating an answer from two years ago. If you're unsatisfied with the answers you've gotten so far, consider posting a bounty to attract fresh ones. \$\endgroup\$ – DMGregory Feb 17 at 11:00
1
\$\begingroup\$

Although it is considered obsolete in favor of the much more powerful AnimationController, the good old Animation component still exists.

It provides you with a very simple way to play an animation clip: GetComponent<Animation>().Play(clipName, mode);

However, before you can play an animation clip by name, you first have to add the animation clip asset to the animator via inspector or using GetComponent<Animation>().AddClip(animationClipAsset, clipName);.

That means you will still need a way to get a reference to the animation clip asset. The easiest way would be to assign it to some inspector variable. But you specifically said "no drag and drop involved", so you might want to get them through Resources (also no longer recommended) or through the new Addressable Asset System.

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ So this depricated way is the only way to do it? Theres no way with the standard assets? Theoretically isnt the animation data available in the file, and can't you manually move the armature bones with C#? Shouldn't there be a way to read the raw animation clips and create new keyframes based on that? Has someone worked on this? \$\endgroup\$ – bluejayke Feb 18 at 2:17
  • \$\begingroup\$ Please do not use the legacy system anymore without real need. The new Playables as outlined by @Wappenull is way more powerful and provides means of creating different Playables at runtime (e.g. movement, sound, script - yes script!) and use them to your liking (even blending the different types). \$\endgroup\$ – loptrinho Mar 21 at 16:44
  • \$\begingroup\$ Note to future readers: My answer totally focus on animation solution but failed to address the point that OP wants "no-drag-drop". @Philipp answer here has valuable way to address that need. \$\endgroup\$ – Wappenull Mar 26 at 8:17
1
\$\begingroup\$

Without using the Animation Controller, you can use Animation Type to Legacy.

enter image description here

Then All you need to attach the script to animation object.

 public Animation animates;

    void Start()
    {
       animates = GetComponenet<Animation>();
    }

    public void Plays()
    {
        animates["ClipName"].normalizedTime = 0.0f;
        animates["ClipName"].speed = 1.0f;
        animates.Play();   
    }
|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ Yes thanks, thats the way I've been doing it, but the problem is that it's legacy, meaning it probably won't be supported for a while, so how can I have a more permanent option? Theoretically the animation states exist in the bytes of the file, should I just parse them myself, and manually animate each bone etc? Is there a better way to do it? \$\endgroup\$ – bluejayke Mar 20 at 21:06
  • \$\begingroup\$ Please do not use the legacy system anymore without real need. The new Playables as outlined above by @Wappenull is way more powerful and provides means of creating different Playables at runtime (e.g. movement, sound, script - yes script!) and use them to your liking (even blending the different types). \$\endgroup\$ – loptrinho Mar 21 at 16:43
0
\$\begingroup\$

To play animation during runtime you need to following things:

  1. Animator component (on runtime)
  2. Avatar of Character
  3. Animator Controller
public class SM : MonoBehaviour
{
    [MenuItem("MyMenu/Create Controller")]
    static void CreateController()
    {
        // Creates the controller
        var controller = UnityEditor.Animations.AnimatorController.CreateAnimatorControllerAtPath("Assets/Mecanim/StateMachineTransitions.controller");

        // Add parameters
        controller.AddParameter("TransitionNow", AnimatorControllerParameterType.Trigger);
        controller.AddParameter("Reset", AnimatorControllerParameterType.Trigger);
        controller.AddParameter("GotoB1", AnimatorControllerParameterType.Trigger);
        controller.AddParameter("GotoC", AnimatorControllerParameterType.Trigger);

        // Add StateMachines
        var rootStateMachine = controller.layers[0].stateMachine;
        var stateMachineA = rootStateMachine.AddStateMachine("smA");
        var stateMachineB = rootStateMachine.AddStateMachine("smB");
        var stateMachineC = stateMachineB.AddStateMachine("smC");

        // Add States
        var stateA1 = stateMachineA.AddState("stateA1");
        var stateB1 = stateMachineB.AddState("stateB1");
        var stateB2 = stateMachineB.AddState("stateB2");
        stateMachineC.AddState("stateC1");
        var stateC2 = stateMachineC.AddState("stateC2"); // don’t add an entry transition, should entry to state by default

        // Add Transitions
        var exitTransition = stateA1.AddExitTransition();
        exitTransition.AddCondition(UnityEditor.Animations.AnimatorConditionMode.If, 0, "TransitionNow");
        exitTransition.duration = 0;

        var resetTransition = rootStateMachine.AddAnyStateTransition(stateA1);
        resetTransition.AddCondition(UnityEditor.Animations.AnimatorConditionMode.If, 0, "Reset");
        resetTransition.duration = 0;

        var transitionB1 = stateMachineB.AddEntryTransition(stateB1);
        transitionB1.AddCondition(UnityEditor.Animations.AnimatorConditionMode.If, 0, "GotoB1");
        stateMachineB.AddEntryTransition(stateB2);
        stateMachineC.defaultState = stateC2;
        var exitTransitionC2 = stateC2.AddExitTransition();
        exitTransitionC2.AddCondition(UnityEditor.Animations.AnimatorConditionMode.If, 0, "TransitionNow");
        exitTransitionC2.duration = 0;

        var stateMachineTransition = rootStateMachine.AddStateMachineTransition(stateMachineA, stateMachineC);
        stateMachineTransition.AddCondition(UnityEditor.Animations.AnimatorConditionMode.If, 0, "GotoC");
        rootStateMachine.AddStateMachineTransition(stateMachineA, stateMachineB);
    }
}
```
|improve this answer|||||
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.