- Home /
Programmatically created AnimationClip will not loop
Hello everyone,
With help from this post, I was able to programmatically create an AnimationClip at runtime with my spritesheet. However, it will not loop.
Here's the code that generates the AnimationClip:
public static AnimationClip LoadNewAnimatedSprite(string folderPath, string animationName, float pixelsPerUnit = 1.0f) {
AnimationClip animClip = new AnimationClip();
Texture2D spriteTexture;
string jsonPath = folderPath + "/" + animationName + ".json";
string imagePath = folderPath + "/" + animationName + ".png";
if (_animations.ContainsKey(jsonPath)) {
return _animations[jsonPath];
}
using (StreamReader reader = File.OpenText(jsonPath)) {
JObject o = (JObject)JToken.ReadFrom(new JsonTextReader(reader));
var meta = o["meta"];
spriteTexture = LoadTexture(imagePath);
var frames = o["frames"];
List<Sprite> sprites = new List<Sprite>();
int i = 0;
foreach (var frame in frames) {
Vector2 pos = new Vector2((int)frame["frame"]["x"], (int)frame["frame"]["y"]);
Vector2 size;
if ((bool)frame["rotated"]) {
size = new Vector2((int)frame["frame"]["h"], (int)frame["frame"]["w"]);
} else {
size = new Vector2((int)frame["frame"]["w"], (int)frame["frame"]["h"]);
}
Rect slice = new Rect(pos, size);
Vector2 pivot = new Vector2((float)frame["pivot"]["x"], (float)frame["pivot"]["y"]);
Sprite newSprite = new Sprite();
newSprite = Sprite.Create(spriteTexture, slice, pivot, pixelsPerUnit);
sprites.Add(newSprite);
}
animClip.frameRate = 3;
EditorCurveBinding spriteBinding = new EditorCurveBinding();
spriteBinding.type = typeof(SpriteRenderer);
spriteBinding.path = "";
spriteBinding.propertyName = "m_Sprite";
ObjectReferenceKeyframe[] spriteKeyFrames = new ObjectReferenceKeyframe[sprites.Count];
for (i = 0; i < sprites.Count; i++) {
spriteKeyFrames[i] = new ObjectReferenceKeyframe();
spriteKeyFrames[i].time = i;
spriteKeyFrames[i].value = sprites[i];
}
AnimationUtility.SetObjectReferenceCurve(animClip, spriteBinding, spriteKeyFrames);
AssetDatabase.CreateAsset(animClip, "assets/TEMP/" + animationName + ".anim");
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
return animClip;
}
And here's the code that creates and adds the clip to an Animator, as well as sets the clip to looping. Note that _loaded is static:
private void InitAnimationController() {
string animation = "Walk_S";
if (!_loaded) {
AnimationClip clip = SpriteCreator.LoadNewAnimatedSprite(Data.Sprite, animation);
var settings = AnimationUtility.GetAnimationClipSettings(clip);
settings.loopTime = true;
AnimationUtility.SetAnimationClipSettings(clip, settings);
clip.wrapMode = WrapMode.PingPong;
controller = AnimatorController.CreateAnimatorControllerAtPath("Assets/TEMP/StateMachineTransition.controller");
controller.AddMotion(clip);
_loaded = true;
}
Animator a = gameObject.AddComponent<Animator>();
a.runtimeAnimatorController = controller;
}
Here's what the saved AnimationClip asset looks like once created. Note that Loop Time is checked and Wrap Mode is set to Ping Pong, as expected.
However, once run, the animation only runs once without looping. If, while running, I uncheck and then recheck Look Time, it will loop, but will wrap as though set to "Loop" regardless of what I change the Wrap Mode to.
I have tried various solutions, like where I set the Loop Time and Wrap Mode. I tried setting both in a coroutine a frame after the clip creation, but I'm met with the same results. Any idea how I can get this working?
Thank you for the help!
Why 'm_Sprite' and not 'Sprite', in spriteBinding.propertyName?
Because it's the actual property name in the native C++ code of the Unity engine. If you want to know the property names of built-in variables, set your asset serialization mode to "force text" and open a serialized asset in a text editor. If you have trouble reading the YA$$anonymous$$L format, have a look at those pages
Answer by NinjaEntertainment · Oct 07, 2017 at 07:23 PM
Hi you must set animation TO LEGACY WHEN YOU PLAY THEM IN SCRIPT GetComponent().Play("ANIMATION NAME"); and find LOOP in inspector... that's all
Hello, thank you for the response!
When I try to set the clip to legacy, it says that legacy animationclips are not allowed in animator controllers and I am left with no sprite image what-so-ever.
Answer by Bunny83 · Mar 16, 2018 at 03:48 PM
Since the question got already bumped:
My guess is you don't properly save your changes to your animationclip. At the end of your "LoadNewAnimatedSprite" method you actually create and store the clip to disk. However you later change the animationclip settings without marking the clip as dirty. You should use EditorUtility.SetDirty on the animationclip after you changed your setting.
When you change the settings in the inspector the inspector will take care of propertly saving the changes.
Your answer
Follow this Question
Related Questions
Animation keeps looping even on WrapMode.Once; 1 Answer
How to avoid animation from resetting after its completion? 1 Answer
Distribute terrain in zones 3 Answers
My Animation Loops 3/4 of the way through 3 Answers
How to set component property value at runtime not having components source? 0 Answers