Esempio n. 1
0
        public void Prepare(List <AnimationInfo> infoList, ExtraBoneInfo extraBoneInfo)
        {
            aniInfo = infoList;
            //extraBoneInfo = extraBoneInfo;
            List <Matrix4x4> bindPose = new List <Matrix4x4>(150);

            // to optimize, MergeBone don't need to call every time
            Transform[] bones = RuntimeHelper.MergeBone(lodInfo[0].skinnedMeshRenderer, bindPose);
            allTransforms = bones;

            if (extraBoneInfo != null)
            {
                List <Transform> list = new List <Transform>();
                list.AddRange(bones);
                Transform[] transforms = gameObject.GetComponentsInChildren <Transform>();
                for (int i = 0; i != extraBoneInfo.extraBone.Length; ++i)
                {
                    for (int j = 0; j != transforms.Length; ++j)
                    {
                        if (extraBoneInfo.extraBone[i] == transforms[j].name)
                        {
                            list.Add(transforms[j]);
                        }
                    }
                    bindPose.Add(extraBoneInfo.extraBindPose[i]);
                }
                allTransforms = list.ToArray();
            }


            AnimationInstancingMgr.Instance.AddMeshVertex(prototype.name,
                                                          lodInfo,
                                                          allTransforms,
                                                          bindPose,
                                                          bonePerVertex);

            foreach (var lod in lodInfo)
            {
                foreach (var cache in lod.vertexCacheList)
                {
                    cache.shadowcastingMode = shadowCastingMode;
                    cache.receiveShadow     = receiveShadow;
                    cache.layer             = layer;
                }
            }

            Destroy(GetComponent <Animator>());
            //Destroy(GetComponentInChildren<SkinnedMeshRenderer>());

            PlayAnimation(0);
        }
        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);
            }
        }
        void BakeWithAnimator()
        {
#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)
            {
                generatedObject = Instantiate(generatedPrefab);
                generatedObject.transform.position = Vector3.zero;
                generatedObject.transform.rotation = Quaternion.identity;
                Animator animator = generatedObject.GetComponentInChildren <Animator>();

                AnimationInstancing script = generatedObject.GetComponent <AnimationInstancing>();
                Debug.Assert(script);
                SkinnedMeshRenderer[] meshRender    = generatedObject.GetComponentsInChildren <SkinnedMeshRenderer>();
                List <Matrix4x4>      bindPose      = new List <Matrix4x4>(150);
                Transform[]           boneTransform = RuntimeHelper.MergeBone(meshRender, bindPose);

                // calculate the bindpose of attached points
                if (generatedFbx)
                {
                    List <Transform> listExtra  = new List <Transform>();
                    Transform[]      trans      = generatedFbx.GetComponentsInChildren <Transform>();
                    Transform[]      bakedTrans = generatedObject.GetComponentsInChildren <Transform>();
                    foreach (var obj in selectExtraBone)
                    {
                        if (!obj.Value)
                        {
                            continue;
                        }

                        for (int i = 0; i != trans.Length; ++i)
                        {
                            Transform tran = trans[i] as Transform;
                            if (tran.name == obj.Key)
                            {
                                bindPose.Add(tran.localToWorldMatrix);
                                listExtra.Add(bakedTrans[i]);
                            }
                        }
                    }

                    Transform[] totalTransform = new Transform[boneTransform.Length + listExtra.Count];
                    System.Array.Copy(boneTransform, totalTransform, boneTransform.Length);
                    System.Array.Copy(listExtra.ToArray(), 0, totalTransform, boneTransform.Length, listExtra.Count);
                    boneTransform = totalTransform;
                    //boneTransform = boneTransform;

                    extraBoneInfo               = new ExtraBoneInfo();
                    extraBoneInfo.extraBone     = new string[listExtra.Count];
                    extraBoneInfo.extraBindPose = new Matrix4x4[listExtra.Count];
                    for (int i = 0; i != listExtra.Count; ++i)
                    {
                        extraBoneInfo.extraBone[i]     = listExtra[i].name;
                        extraBoneInfo.extraBindPose[i] = bindPose[bindPose.Count - listExtra.Count + i];
                    }
                }
                Reset();
                AddMeshVertex2Generate(meshRender, boneTransform, bindPose.ToArray());

                Transform rootNode = meshRender[0].rootBone;
                for (int j = 0; j != meshRender.Length; ++j)
                {
                    meshRender[j].enabled = true;
                }
                animator.applyRootMotion = true;
                totalFrame = 0;

                UnityEditor.Animations.AnimatorController controller = animator.runtimeAnimatorController as UnityEditor.Animations.AnimatorController;
                Debug.Assert(controller.layers.Length > 0);
                cacheTransition.Clear();
                cacheAnimationEvent.Clear();
                UnityEditor.Animations.AnimatorControllerLayer layer = controller.layers[0];
                AnalyzeStateMachine(layer.stateMachine, animator, meshRender, 0, aniFps, 0);
                generateCount = generateInfo.Count;
            }
        }
        private void OnGUI()
        {
            GUI.skin.label.richText = true;
            GUILayout.BeginHorizontal();
            {
                GUILayout.FlexibleSpace();
            }
            GUILayout.EndHorizontal();

            GameObject prefab = EditorGUILayout.ObjectField("Asset to Generate", generatedPrefab, typeof(GameObject), true) as GameObject;

            if (prefab != generatedPrefab)
            {
                generateAnims.Clear();
                customClips.Clear();
                generatedPrefab = prefab;

                SkinnedMeshRenderer[] meshRender = generatedPrefab.GetComponentsInChildren <SkinnedMeshRenderer>();
                List <Matrix4x4>      bindPose   = new List <Matrix4x4>(150);
                boneTransform = RuntimeHelper.MergeBone(meshRender, bindPose);
            }

            bool error = false;

            if (generatedPrefab)
            {
                exposeAttachments = EditorGUILayout.Toggle("Enable Attachments", exposeAttachments);
                if (exposeAttachments)
                {
                    showAttachmentSetting = EditorGUILayout.Foldout(showAttachmentSetting, "Attachment setting");
                    if (showAttachmentSetting)
                    {
                        GameObject fbx = EditorGUILayout.ObjectField("   FBX", generatedFbx, typeof(GameObject), false) as GameObject;
                        if (fbx != generatedFbx)
                        {
                            SkinnedMeshRenderer[] meshRender = generatedPrefab.GetComponentsInChildren <SkinnedMeshRenderer>();
                            List <Matrix4x4>      bindPose   = new List <Matrix4x4>(150);
                            boneTransform = RuntimeHelper.MergeBone(meshRender, bindPose);

                            generatedFbx = fbx;
                            var allTrans = generatedPrefab.GetComponentsInChildren <Transform>().ToList();
                            allTrans.RemoveAll(q => boneTransform.Contains(q));
                            selectExtraBone.Clear();
                            for (int i = 0; i != allTrans.Count; ++i)
                            {
                                selectExtraBone.Add(allTrans[i].name, false);
                            }
                        }

                        var temp = new Dictionary <string, bool>();
                        foreach (var obj in selectExtraBone)
                        {
                            temp[obj.Key] = obj.Value;
                        }
                        scrollPosition2 = GUILayout.BeginScrollView(scrollPosition2);
                        foreach (var obj in temp)
                        {
                            bool value = EditorGUILayout.Toggle(string.Format("   {0}", obj.Key), obj.Value);
                            selectExtraBone[obj.Key] = value;
                        }
                        GUILayout.EndScrollView();
                    }
                }
                else
                {
                    generatedFbx = null;
                }

                aniFps = EditorGUILayout.IntSlider("FPS", aniFps, 1, 120);

                Animator animator = generatedPrefab.GetComponentInChildren <Animator>();
                if (animator == null)
                {
                    EditorGUILayout.LabelField("Error: The prefab should have a Animator Component.");
                    return;
                }
                if (animator.runtimeAnimatorController == null)
                {
                    EditorGUILayout.LabelField("Error: The prefab's Animator should have a Animator Controller.");
                    return;
                }
                var        clips       = GetClips(animator);
                string[]   clipNames   = generateAnims.Keys.ToArray();
                int        totalFrames = 0;
                List <int> frames      = new List <int>();
                foreach (var clipName in clipNames)
                {
                    if (!generateAnims[clipName])
                    {
                        continue;
                    }

                    AnimationClip clip = clips.Find(delegate(AnimationClip c) {
                        if (c != null)
                        {
                            return(c.name == clipName);
                        }
                        return(false);
                    });
                    int framesToBake = clip ? (int)(clip.length * aniFps / 1.0f) : 0;
                    totalFrames += framesToBake;
                    frames.Add(framesToBake);
                }

                int textureCount = 1;
                int textureWidth = CalculateTextureSize(out textureCount, frames.ToArray(), boneTransform);
                error = textureCount == 0;
                if (textureCount == 0)
                {
                    EditorGUILayout.LabelField("Error: There is certain animation's frames which is larger than a whole texture.");
                }
                else if (textureCount == 1)
                {
                    EditorGUILayout.LabelField(string.Format("Animation Texture wiil be one {0} X {1} texture", textureWidth, textureWidth));
                }
                else
                {
                    EditorGUILayout.LabelField(string.Format("Animation Texture wiil be {2} 1024 X 1024 and one {0} X {1} textures", textureWidth, textureWidth, textureCount - 1));
                }

                scrollPosition = GUILayout.BeginScrollView(scrollPosition);
                foreach (var clipName in clipNames)
                {
                    AnimationClip clip = clips.Find(delegate(AnimationClip c) {
                        if (c != null)
                        {
                            return(c.name == clipName);
                        }
                        return(false);
                    });
                    int framesToBake = clip ? (int)(clip.length * aniFps / 1.0f) : 0;
                    GUILayout.BeginHorizontal();
                    {
                        generateAnims[clipName] = EditorGUILayout.Toggle(string.Format("({0}) {1} ", framesToBake, clipName), generateAnims[clipName]);
                        GUI.enabled             = generateAnims[clipName];
                        //frameSkips[clipName] = Mathf.Clamp(EditorGUILayout.IntField(frameSkips[clipName]), 1, fps);
                        GUI.enabled = true;
                    }
                    GUILayout.EndHorizontal();
                    if (framesToBake > 5000)
                    {
                        GUI.skin.label.richText = true;
                        EditorGUILayout.LabelField("<color=red>Long animations degrade performance, consider using a higher frame skip value.</color>", GUI.skin.label);
                    }
                }
                GUILayout.EndScrollView();
            }

            if (generatedPrefab && !error)
            {
                if (GUILayout.Button(string.Format("Generate")))
                {
                    //BakeAnimation();
                    BakeWithAnimator();
                }
            }
        }