private void ApplyRootMotion(AnimationInstancing instance) { AnimationInfo info = instance.GetCurrentAnimationInfo(); if (info == null || !info.rootMotion) { return; } int preSampleFrame = (int)instance.curFrame; int nextSampleFrame = (int)(instance.curFrame + 1.0f); if (nextSampleFrame >= info.totalFrame) { return; } Vector3 preVelocity = info.velocity[preSampleFrame]; Vector3 nextVelocity = info.velocity[nextSampleFrame]; Vector3 velocity = Vector3.Lerp(preVelocity, nextVelocity, instance.curFrame - preSampleFrame); Vector3 angularVelocity = Vector3.Lerp(info.angularVelocity[preSampleFrame], info.angularVelocity[nextSampleFrame], instance.curFrame - preSampleFrame); { Quaternion localQuaternion = instance.worldTransform.localRotation; Quaternion delta = Quaternion.Euler(angularVelocity * Time.deltaTime); localQuaternion = localQuaternion * delta; Vector3 offset = velocity * Time.deltaTime; offset = localQuaternion * offset; //offset.y = 0.0f; Vector3 localPosition = instance.worldTransform.localPosition; localPosition += offset; #if UNITY_5_6_OR_NEWER instance.worldTransform.SetPositionAndRotation(localPosition, localQuaternion); #else instance.worldTransform.localPosition = localPosition; instance.worldTransform.localRotation = localQuaternion; #endif } }
private void PrepareBoneTexture(ArrayList infoList) { int count = 1; int[] frames = new int[infoList.Count]; for (int i = 0; i != infoList.Count; ++i) { AnimationInfo info = infoList[i] as AnimationInfo; frames[i] = info.totalFrame; } int textureWidth = CalculateTextureSize(out count, frames); //int textureHeight = textureWidth; Debug.Assert(textureWidth > 0); bakedBoneTexture = new Texture2D[count]; TextureFormat format = TextureFormat.RGBAHalf; for (int i = 0; i != count; ++i) { int width = count > 1 && i < count ? stardardTextureSize[stardardTextureSize.Length - 1] : textureWidth; bakedBoneTexture[i] = new Texture2D(width, width, format, false); bakedBoneTexture[i].filterMode = FilterMode.Point; } }
public bool InitializeAnimation() { // if (prefab == null) // prefab = GameObject.Find(prefabName); Debug.Assert(cfgName != ""); // GameObject thisPrefab = prefab; isMeshRender = false; if (lodInfo[0].skinnedMeshRenderer.Length == 0) { // This is only a MeshRenderer, it has no animations. isMeshRender = true; AnimationInstancingMgr.Instance.AddMeshVertex(this, lodInfo, null, null, bonePerVertex); return(true); } if (animationInfo == null) { animationInfo = AnimationManager.Instance.FindAnimationInfo(cfgName, this); } if (animationInfo != null) { aniInfo = animationInfo.listAniInfo; Prepare(aniInfo, animationInfo.extraBoneInfo); } if (searchInfo == null) { searchInfo = new AnimationInfo(); } if (comparer == null) { comparer = new ComparerHash(); } return(true); }
public void PlayAnimation(int animationIndex) { if (aniInfo == null) { return; } if (animationIndex == aniIndex) { return; } Debug.Assert(animationIndex < aniInfo.Count); if (0 <= animationIndex && animationIndex < aniInfo.Count) { aniIndex = animationIndex; curAnimation = GetCurrentAnimationInfo(); curFrame = 0.0f; oldFrame = 0.0f; eventIndex = -1; aniTextureIndex = curAnimation.textureIndex; } RefreshAttachmentAnimation(animationIndex); }
private void UpdateAnimationEvent() { AnimationInfo info = GetCurrentAnimationInfo(); if (info == null) { return; } if (info.eventList.Count == 0) { return; } if (aniEvent == null) { float time = curFrame / info.fps; for (int i = eventIndex >= 0? eventIndex: 0; i < info.eventList.Count; ++i) { if (info.eventList[i].time > time) { aniEvent = info.eventList[i]; eventIndex = i; break; } } } if (aniEvent != null) { float time = curFrame / info.fps; if (aniEvent.time <= time) { gameObject.SendMessage(aniEvent.function, aniEvent); aniEvent = null; } } }
private void SaveAnimationInfo(string name) { string folderName = "AnimationTexture"; string path = Application.dataPath + "/" + CLPathCfg.self.basePath + "/upgradeRes4Dev/priority/" + folderName + "/"; if (!Directory.Exists(path)) { AssetDatabase.CreateFolder("Assets", folderName); } FileStream file = File.Open(path + name + ".bytes", FileMode.Create); BinaryWriter writer = new BinaryWriter(file); writer.Write(aniInfo.Count); foreach (var obj in aniInfo) { AnimationInfo info = (AnimationInfo)obj; //writer.Write(info.animationNameHash); writer.Write(info.animationName); writer.Write(info.animationIndex); writer.Write(info.textureIndex); writer.Write(info.totalFrame); writer.Write(info.fps); writer.Write(info.rootMotion); if (info.rootMotion) { Debug.Assert(info.totalFrame == info.velocity.Length); for (int i = 0; i != info.velocity.Length; ++i) { writer.Write(info.velocity[i].x); writer.Write(info.velocity[i].y); writer.Write(info.velocity[i].z); writer.Write(info.angularVelocity[i].x); writer.Write(info.angularVelocity[i].y); writer.Write(info.angularVelocity[i].z); } } writer.Write(info.eventList.Count); foreach (var evt in info.eventList) { writer.Write(evt.function); writer.Write(evt.floatParameter); writer.Write(evt.intParameter); writer.Write(evt.stringParameter); writer.Write(evt.time); writer.Write(evt.objectParameter); } } writer.Write(exposeAttachments); if (exposeAttachments) { writer.Write(extraBoneInfo.extraBone.Length); for (int i = 0; i != extraBoneInfo.extraBone.Length; ++i) { writer.Write(extraBoneInfo.extraBone[i]); } for (int i = 0; i != extraBoneInfo.extraBindPose.Length; ++i) { for (int j = 0; j != 16; ++j) { writer.Write(extraBoneInfo.extraBindPose[i][j]); } } } Texture2D[] texture = bakedBoneTexture; writer.Write(texture.Length); writer.Write(textureBlockWidth); writer.Write(textureBlockHeight); for (int i = 0; i != texture.Length; ++i) { byte[] bytes = texture[i].GetRawTextureData(); writer.Write(texture[i].width); writer.Write(texture[i].height); writer.Write(bytes.Length); writer.Write(bytes); } file.Close(); aniInfo.Clear(); }
void BakeAnimation() { #if UNITY_ANDROID || UNITY_IPHONE Debug.LogError("You can't bake animations on IOS or Android. Please switch to PC."); return; #endif if (generatedPrefab != null) { GameObject obj = Instantiate(generatedPrefab); obj.transform.position = Vector3.zero; obj.transform.rotation = Quaternion.identity; Animator animator = obj.GetComponentInChildren <Animator>(); AnimationInstancing script = obj.GetComponent <AnimationInstancing>(); Debug.Assert(script); SkinnedMeshRenderer[] meshRender = obj.GetComponentsInChildren <SkinnedMeshRenderer>(); List <Matrix4x4> bindPose = new List <Matrix4x4>(150); Transform[] boneTransform = RuntimeHelper.MergeBone(meshRender, bindPose); Reset(); AddMeshVertex2Generate(meshRender, boneTransform, bindPose.ToArray()); Transform rootNode = meshRender[0].rootBone; for (int j = 0; j != meshRender.Length; ++j) { meshRender[j].enabled = true; } int frames = 0; var clips = GetClips(true); foreach (AnimationClip animClip in clips) { //float lastFrameTime = 0; int aniName = animClip.name.GetHashCode(); int bakeFrames = Mathf.CeilToInt(animClip.length * aniFps); AnimationInfo info = new AnimationInfo(); info.animationNameHash = aniName; info.animationIndex = frames; info.totalFrame = bakeFrames; //bool rotationRootMotion = false, positionRootMotion = false; //for (int i = 0; i < bakeFrames; i += 1) //{ // float bakeDelta = Mathf.Clamp01(((float)i / bakeFrames)); // float animationTime = bakeDelta * animClip.length; // animClip.SampleAnimation(obj, animationTime); // info.position[i] = rootNode.localPosition; // info.rotation[i] = rootNode.localRotation; // if (i > 0 && info.position[i] != info.position[i - 1]) // { // positionRootMotion = true; // } // if (i > 0 && info.rotation[i] != info.rotation[i - 1]) // { // rotationRootMotion = true; // } //} //info.rootMotion = positionRootMotion; Matrix4x4 rootMatrix1stFrame = Matrix4x4.identity; animator.applyRootMotion = true; animator.Play("TestState", 0); // animator.StartRecording(bakeFrames); // for (int i = 0; i < bakeFrames; i += 1) // { // animator.Update(1.0f / m_fps); // } // animator.StopRecording(); // // animator.StartPlayback(); // animator.playbackTime = 0; //AnimationInstancing script = m_prefab.GetComponent<AnimationInstancing>(); for (int i = 0; i < bakeFrames; i += 1) { //float bakeDelta = Mathf.Clamp01(((float)i / bakeFrames)); //float animationTime = bakeDelta * animClip.length; //float normalizedTime = animationTime / animClip.length; //UnityEditor.Animations.AnimatorController ac = animator.runtimeAnimatorController; //UnityEditorInternal.StateMachine sm = ac.GetLayerStateMachine(0); //AnimatorStateInfo nameInfo = animator.GetCurrentAnimatorStateInfo(0); // if (lastFrameTime == 0) // { // float nextBakeDelta = Mathf.Clamp01(((float)(i + 1) / bakeFrames)); // float nextAnimationTime = nextBakeDelta * animClip.length; // lastFrameTime = animationTime - nextAnimationTime; // } // animator.Update(animationTime - lastFrameTime); // lastFrameTime = animationTime; animator.Update(1.0f / bakeFrames); //animClip.SampleAnimation(obj, animationTime); //if (i == 0) //{ // rootMatrix1stFrame = boneTransform[0].localToWorldMatrix; //} for (int j = 0; j != meshRender.Length; ++j) { GenerateBoneMatrix(meshRender[j].name.GetHashCode(), aniName, i, rootMatrix1stFrame, info.rootMotion); } } aniInfo.Add(info); frames += bakeFrames; SetupAnimationTexture(aniInfo); } //AnimationInstancingMgr.Instance.ExportBoneTexture(m_prefab.name); SaveAnimationInfo(generatedPrefab.name); DestroyImmediate(obj); } }
public void SetupAnimationTexture(ArrayList infoList) { int preNameCode = generateObjectData[0].stateName; //int preTextureIndex = m_bakedTextureIndex; for (int i = 0; i != currentDataIndex; ++i) { GenerateOjbectInfo matrixData = generateObjectData[i]; if (matrixData.boneMatrix == null) { continue; } if (preNameCode != matrixData.stateName) { preNameCode = matrixData.stateName; int totalFrames = currentDataIndex - i; for (int j = i; j != currentDataIndex; ++j) { if (preNameCode != generateObjectData[j].stateName) { totalFrames = j - i; break; } } int width = bakedBoneTexture[bakedTextureIndex].width; int height = bakedBoneTexture[bakedTextureIndex].height; int y = pixely; int currentLineBlockCount = (width - pixelx) / textureBlockWidth % (width / textureBlockWidth); totalFrames -= currentLineBlockCount; if (totalFrames > 0) { int framesEachLine = width / textureBlockWidth; y += (totalFrames / framesEachLine) * textureBlockHeight; y += currentLineBlockCount > 0 ? textureBlockHeight : 0; if (height < y + textureBlockHeight) { ++bakedTextureIndex; pixelx = 0; pixely = 0; Debug.Assert(bakedTextureIndex < bakedBoneTexture.Length); } } foreach (var obj in infoList) { AnimationInfo info = obj as AnimationInfo; if (info.animationNameHash == matrixData.stateName) { info.animationIndex = pixelx / textureBlockWidth + pixely / textureBlockHeight * bakedBoneTexture[bakedTextureIndex].width / textureBlockWidth; info.textureIndex = bakedTextureIndex; } } } if (matrixData.boneMatrix != null) { Debug.Assert(pixely + textureBlockHeight <= bakedBoneTexture[bakedTextureIndex].height); Color[] color = UtilityHelper.Convert2Color(matrixData.boneMatrix, boneCount); bakedBoneTexture[bakedTextureIndex].SetPixels(pixelx, pixely, textureBlockWidth, textureBlockHeight, color); matrixData.frameIndex = pixelx / textureBlockWidth + pixely / textureBlockHeight * bakedBoneTexture[bakedTextureIndex].width / textureBlockWidth; pixelx += textureBlockWidth; if (pixelx + textureBlockWidth > bakedBoneTexture[bakedTextureIndex].width) { pixelx = 0; pixely += textureBlockHeight; } if (pixely + textureBlockHeight > bakedBoneTexture[bakedTextureIndex].height) { Debug.Assert(generateObjectData[i + 1].stateName != matrixData.stateName); ++bakedTextureIndex; pixelx = 0; pixely = 0; Debug.Assert(bakedTextureIndex < bakedBoneTexture.Length); } } else { Debug.Assert(false); ArrayList list = generateMatrixDataPool[matrixData.stateName]; GenerateOjbectInfo originalData = list[matrixData.boneListIndex] as GenerateOjbectInfo; matrixData.frameIndex = originalData.frameIndex; } } currentDataIndex = 0; }