- Home /
adding a clip to a animation component via script
Is it possible to do this? I get an error message telling me that "Property UnityEngine.component.animation is Read-Only". Does this mean that you cannot alter the animation component's properties via scripting?
Here's my script so far:
@script RequireComponent(Animation)
function Start () {
animation.animation = "EnemyAdvanceLeft";
}
function Update () {
}
My gut is telling me that Unity probably doesn't know where to find the animation called "EnemyAdvanceLeft". It's just that the error message I received does not indicate that's the primary issue.
Thanks.
Answer by MP0732 · Jun 25, 2012 at 12:20 PM
In the end, I ended up assigning both possible scripts to each prefab, then simply assigning the one to be played via script. This means that each instance of the prefab carries an animation it does not need, but I found this to be simpler than trying to assign it during run-time, as I am still getting error messages when I try to do this.
Thanks again Mike for your help.
Answer by whydoidoit · Jun 21, 2012 at 08:25 PM
You need to add the actual clip - with animation.AddClip().
Here's my C# script for adding all of the animations in a folder:
using UnityEngine;
using System.Collections;
using System.Linq;
[AddComponentMenu("System/Load Animations")]
public class LoadAnimations : MonoBehaviour {
public new string name;
void Awake()
{
var clips = Resources.LoadAll("Animations/" + name, typeof(AnimationClip)).Cast<AnimationClip>();
foreach (var c in clips)
{
animation.AddClip(c, c.name.Contains("@") ? c.name.Substring(c.name.LastIndexOf("@") + 1) : c.name);
}
foreach (var a in animation.Cast<AnimationState>())
{
a.enabled = true;
}
}
}
Well, I've looked around the web to try to figure out your script, and I'm sorry I just can't make sense of it.
I guess I don't understand why I can't just tell Unity where to find the animation clip I want to load and go from there.
Sure so you can add the clip if it is stored in a variable too, that script is loading them from the resources folder. Using a variable it would look like this:
var myClip : AnimationClip;
Or maybe
var myClips : AnimationClip[];
Then you would add them using:
animation.AddClip(myClip);
or: for(var a : AnimationClip in myClips) { animation.AddClip(a); }
Then you would just drag them on to the object. Or you can name them nameOf$$anonymous$$y$$anonymous$$odel@nameOfAnimation and there's some settings to store the animations in the root model.
Answer by MP0732 · Jun 22, 2012 at 05:21 PM
OK, thanks. Well, I loaded the C# script via the Immediate Window in MonoDevelop.
Then I tried to add the animation using the following script which I attached via code to the game object I had instantiated. It failed, and I got the following error: "No appropriate version of 'UnityEngine.Animation.AddClip' for the argument list '(UnityEngine.AnimationClip)' was found."
Here's my script:
@script RequireComponent(Animation)
function Start () {
var enemyAdvanceLeft : AnimationClip;
animation.AddClip(enemyAdvanceLeft);
}
function Update () {
}
Any idea what I'm doing wrong? Thanks again.
You need to actually get the animation clip itself from somewhere - what you have done there is define a variable with nothing in it. However, I've also made a mistake :( You have to do animation.AddClip(clip, name)
So you need to make enemyAdvanceLeft a script level variable and assign it in the inspector.@script RequireComponent(Animation)
var enemyAdvanceLeft : AnimationClip;
function Start () {
animation.AddClip(enemyAdvanceLeft,"advanceLeft");
}
O$$anonymous$$, but that's the problem. I need to assign the animation during game time, i.e. via code. I can't assign it in the Inspector because the game object to which it is supposed to be attached is instantiated while the game is running.
Is that possible?
Also, I guess I thought that I ran your C# script above in order to make all of the animations I had created accessible via scripting. But maybe I was wrong about its purpose?
So you are going to need to either:
Load it from the resources folder doing this:
enemyAdvanceLeft = Resources.Load("Path/To/Your/Animation", typeof(AnimationClip)) as AnimationClip;
Create a special holder object for your animations.
Create an empty game object
- attach a singleton script to it that has an array of animations clips that you assign in the inspector
script has a static member initialized in Awake()
It's set to don't destroy on load
var clips : AnimationClip[]; static var Instance : YourScriptName; function Awake() { Instance = this; DontDestroyOnLoad(gameObject); }
The from elsewhere you can access the clips using
YourScriptName.clips[0]; //etc
Answer by nonehill · Apr 09, 2015 at 06:16 PM
Check this out awesome example https://github.com/nonehill/DynamicallyLoadingAnimation
Answer by phreakhead · Sep 10, 2017 at 03:21 AM
If you don't want to mark your animations as legacy, you can use the new Playables API to play non-legacy AnimationClips:
private List<PlayableGraph> graphs = new List<PlayableGraph> ();
// Just call this function when you want to play an AnimationClip on a specific GameObject.
// from https://docs.unity3d.com/Manual/Playables-Examples.html
private PlayableGraph playAnim(AnimationClip clip, GameObject obj) {
PlayableGraph playableGraph;
AnimationPlayableUtilities.PlayClip(obj.AddComponent<Animator>(), clip, out playableGraph);
// save all graphs we create and destroy them at the end of our scene.
// you might need to optimize this if you make a lot of animations.
graphs.Add (playableGraph);
return playableGraph;
}
void OnDisable() {
foreach (var g in graphs) {
g.Destroy();
}
graphs.Clear ();
}
Your answer
