Hi. I am currently bound in performance by skinning calculations. In the past, when I was using a different engine, I baked 33 frame animation into 33 meshes, which helped a lot. What is the best way to do the same in Unity? I heard about a skinned mesh instancing feature and SkinnedMeshRenderer.BakeMesh method, but wasn’t able to make them work (don’t really understand how to use them at all).
My scenario is one skinned model with two animations, which is used for 1 - 30 actors in a scene. Animations are not synced between different actors in any way.
Thanks.
Same thing here. I know this is kind of an older thread, but I’m having the exact same problem.
I was told the skinning was done by the CPU (a higher up decision made by the design team), and that they actually toyed with the idea of making it done on the GPU, but decided to go with the CPU.
Considering my game is about 80% CPU and 20% GPU right now, having the skinned mesh rendering done by the CPU is bad for my fps. Very bad. I would love to have a tutorial from someone who knows how to do what you suggested manunt.
Here is my current thought:
At the beginning of the game start playing the animation. Then use some “if animation.time = certain time” in the Update() function to call SkinnedMeshRenderer.BakeMesh function at certain times in the animation in order to get a sequential “snapshot” of each of the mesh’s positions along the animation sequence.
So in other words, bake meshes super quick to get about 30 meshes. Then linearly interpolate between each mesh to create a smooth animation.
I’ve only been learning Unity for a year now, so I have absolutely no idea if this could work. Could someone write a tutorial on how to use SkinnedMeshRenderer.BakeMesh to demonstrate how to make (for example) a simple “idle” animation for a basic character?
This script shows how to bake an animation clip. The important thing is you need to call Sample on the animation before baking so the bones are in the right place.
using UnityEngine;
using System.Collections;
public class BakeMeshTest : MonoBehaviour
{
void Start()
{
// Get the state for the clip we want to bake
AnimationState clipState = m_animation[m_clipToBake];
if (clipState == null)
{
Debug.LogError(string.Format("Unable to get clip '{0}'", m_clipToBake), this);
return;
}
// Start playing the clip
m_animation.Play(m_clipToBake, PlayMode.StopAll);
// Set time to start
clipState.time = 0.0f;
// Calculate time between baked frames
float deltaTime = clipState.length / (float)(m_numFramesToBake - 1);
// Bake the frames
for (int frameIndex = 0; frameIndex < m_numFramesToBake; ++frameIndex)
{
string frameName = string.Format("BakedFrame{0}", frameIndex);
// Create a mesh to store this frame
Mesh frameMesh = new Mesh();
frameMesh.name = frameName;
// Sample animation to get bones in the right place
m_animation.Sample();
// Bake the mesh
m_skinnedMeshRenderer.BakeMesh(frameMesh);
// Setup game object to show frame
GameObject frameGO = new GameObject(frameName);
frameGO.name = frameName;
frameGO.transform.position = transform.position + new Vector3(frameIndex, 0.0f, 0.0f);
// Setup mesh filter
MeshFilter meshFilter = frameGO.AddComponent<MeshFilter>();
meshFilter.mesh = frameMesh;
// Setup mesh renderer
MeshRenderer meshRenderer = frameGO.AddComponent<MeshRenderer>();
meshRenderer.sharedMaterials = m_skinnedMeshRenderer.sharedMaterials;
// Move to next frame time
clipState.time += deltaTime;
}
// Stop playing
m_animation.Stop();
}
[SerializeField]
Animation m_animation; // Animation component used for baking
[SerializeField]
SkinnedMeshRenderer m_skinnedMeshRenderer; // Skinned mesh renderer used for baking
[SerializeField]
string m_clipToBake = "Idle"; // Name of the animation clip to bake
[SerializeField]
int m_numFramesToBake = 30; // Number of frames to bake
}
3 Likes
Wow. Thanks Gibbonator. That’s pretty much along the lines of what I was going to try to do.
Thank you very much. 
Has anybody managed to do this with Mecanim anims?
Last time I looked at Mecanim, it seemed to be missing an absolutely critical feature, the ability to set the current time in an animation/animation state.
(But Mecanim is also all very ‘indirect’ - you can’t tell it to do anything right now, you have to ask it nicely, and maybe it’ll do it over the next few frames - which might be nice when you want a smooth blend, but it’s rather a problem if you’re trying to do something like this…)