Hi,
I implemented full body procedural animation. As I want to use the benefits of the animation system (such as layers, cross fade etc.) so I used AnimationCurves to implement my animation. I change the keyframes of those curves each frame, using the following code:
for (int i = 0 ; i < numOfBones ;i++)
{
curve.keys= new Keyframe[2] {new Keyframe(0,bonesRotations[i].x),
new Keyframe(1,bonesRotations[i].x)};
animation["ProceduralAnim"].clip.SetCurve(boneName[i],typeof(Transform),
propertyNames[j], curve);
curve.keys= new Keyframe[2] {new Keyframe(0,bonesRotations[i].y),
new Keyframe(1,bonesRotations[i].y)};
animation["ProceduralAnim"].clip.SetCurve(boneName[i],typeof(Transform),
propertyNames[j], curve);
curve.keys= new Keyframe[2] {new Keyframe(0,bonesRotations[i].z),
new Keyframe(1,bonesRotations[i].z)};
animation["ProceduralAnim"].clip.SetCurve(boneName[i],typeof(Transform),
propertyNames[j], curve);
curve.keys= new Keyframe[2] {new Keyframe(0,bonesRotations[i].w),
new Keyframe(1,bonesRotations[i].w)};
animation["ProceduralAnim"].clip.SetCurve(boneName[i],typeof(Transform),
propertyNames[j], curve);
}
This method works. However its performance is bad, especially because the SetCurve method. I guess this method looks for the GameObject it needs to animate and this is the reason for the performance hit. I sure just setting the rotation manually isn’t that slow, but as I said I want to have the benefit of the animation system if possible.
So my questions are:
Is there a way to directly manipulate AnimationCurves without the need to use SetCurve every frame?
Is a way to set an AnimationCurve in a clip using the animated object instead of a string with the path to it so the searching won’t take so much time?
Is it possible to inherite from AnimationCurve and implement AnimationCurves that will take the keyframe data they need from data I’ll supply each frame. the creating a clip from such curves?
Thanks
yinono
Any other remark from somebody that tried to implement such
Thanks
I haven’t messed with the animation features myself, but here are some general observations (partly based on me doing something similar with the particle-system).
First, make sure you cache any object references. That would be something like this:
(in public variable section)
private var proceduralClip: AnimationClip;
(in Awake)
proceduralClip = animation["ProceduralAnim"].clip;
(in Update)
proceduralClip.SetCurve( ... );
Secondly don’t use “new” every frame if you can possibly avoid it!! Declare explicitly typed variables and reuse them!
You can reuse the same Keyframe variable by changing its properties:
Same with your AnimationKeys/Curves - declare them explicit in the beginning and reuse them over and over.
One of the reason that using new is so bad is that you’re forcing the garbage collector to run every single frame!!
Explicitly typed variables are also much better than loosely typed ones because they get compiled into much more efficient code.
Finally if some of the Curve/Keyframe data is the same each frame you can preload those values in Awake and just update the changed stuff in Update.
then my animation doesn’t play at all.
Moreover it looks like the most time consuming line in the code is the SetCurve line, and I don’t know about any other way to perform the same task.
I’ll be glad for any offer about how to optimize the codes sample I added in the previous post.
The only change I could to to the code is to keep a reference to animation[“ProceduralAnim”].clip. I tried this and there was no noticeable change in performance.
Keyframe is a struct, so new instances are created on the stack and do not cause allocation in main memory. This makes creating new Keyframes almost free and certainly not the cause of the performance issue. In fact, caching and re-using the Keyframes wouldn’t gain you anything, as structs are copied when passed to functions anyway.