Ejemplo n.º 1
0
        public override void DrawUI(Rect rect)
        {
            if (GUILayout.Button("加载预览"))
            {
                var prefab = AssetDatabase.LoadAssetAtPath <GameObject>(AVATAR_PATH);
                PreviewInstance           = EditorHelper.InstantiateGoByPrefab(prefab, null);
                PreviewInstance.hideFlags = HideFlags.HideAndDontSave;
                _previewAnimator          = AssetDatabase.LoadAssetAtPath <AnimatorController>(PREVIEW_ANIMCONTROLLER_PATH);
                _animationClip            = AssetDatabase.LoadAssetAtPath <AnimationClip>(CLIP_PATH);
                var states = _previewAnimator.layers[0].stateMachine.states;
                foreach (var item in states)
                {
                    if (item.state.name == "Preview")
                    {
                        _animatorState = item.state;
                        break;
                    }
                }

                InitController();

                _avatarPreview = new AvatarPreview(_animator, _animationClip);
                _avatarPreview.OnAvatarChangeFunc = SetPreviewAvatar;
                _avatarPreview.fps = Mathf.RoundToInt(_animationClip.frameRate);
                _avatarPreview.ShowIKOnFeetButton = (_animationClip as Motion).isHumanMotion;
                _avatarPreview.ResetPreviewFocus();

                // force an update on timeControl if AvatarPreviewer is closed when creating/editing animation curves
                // prevent from having a nomralizedTime == -inf
                if (_avatarPreview.timeControl.currentTime == Mathf.NegativeInfinity)
                {
                    _avatarPreview.timeControl.Update();
                }
            }

            if (null != _avatarPreview)
            {
                GUILayout.Label("", GUILayout.Height(300), GUILayout.Width(500));
                if (Event.current.type == EventType.Repaint)
                {
                    _avatarPreview.timeControl.loop = true;
                    _avatarPreview.timeControl.Update();
                    AnimationClipSettings previewInfo = AnimationUtility.GetAnimationClipSettings(_animationClip);
                    float normalizedTime = previewInfo.stopTime - previewInfo.startTime != 0
                        ? (_avatarPreview.timeControl.currentTime - previewInfo.startTime) /
                                           (previewInfo.stopTime - previewInfo.startTime)
                        : 0.0f;
                    _avatarPreview.Animator.Play(0, 0, normalizedTime);
                    _avatarPreview.Animator.Update(_avatarPreview.timeControl.deltaTime);
                }

                _avatarPreview.DoAvatarPreview(PREVIEW_RECT, Constants.preBackgroundSolid);
            }
        }
        private void Init(Animator scenePreviewObject, Motion motion)
        {
            if (m_AvatarPreview == null)
            {
                m_AvatarPreview = new AvatarPreview(scenePreviewObject, motion);
                m_AvatarPreview.OnAvatarChangeFunc = OnPreviewAvatarChanged;
                m_AvatarPreview.ShowIKOnFeetButton = false;
                m_AvatarPreview.ResetPreviewFocus();
            }

            if (m_Timeline == null)
            {
                m_Timeline          = new TimelineControl();
                m_MustSampleMotions = true;
            }

            CreateController();

            if (m_ParameterInfoList == null)
            {
                CreateParameterInfoList();
            }
        }
        private void ResampleTransition(AnimatorStateTransition transition, AvatarMask layerMask, TransitionInfo info, Animator previewObject)
        {
            m_IsResampling    = true;
            m_MustResample    = false;
            m_ValidTransition = true;

            bool resetTimeSettings = m_RefTransition != transition;

            m_RefTransition     = transition;
            m_RefTransitionInfo = info;

            m_LayerMask = layerMask;

            if (m_AvatarPreview != null)
            {
                m_AvatarPreview.OnDisable();
                m_AvatarPreview = null;
            }

            ClearController();

            Motion sourceStateMotion = m_RefSrcState.motion;

            Init(previewObject, sourceStateMotion != null ? sourceStateMotion : m_RefDstState.motion);

            if (m_Controller == null)  //  did not create controller
            {
                m_IsResampling = false;
                return;
            }

            // since transform might change during sampling, and could alter the default valuesarray, and break recording
            m_AvatarPreview.Animator.allowConstantClipSamplingOptimization = false;

            // sample all frames

            m_StateMachine.defaultState = m_DstState;
            m_Transition.mute           = true;
            AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, m_Controller);
            m_AvatarPreview.Animator.Update(0.00001f);
            WriteParametersInController();
            m_AvatarPreview.Animator.SetLayerWeight(m_LayerIndex, 1);

            float nextStateDuration = m_AvatarPreview.Animator.GetCurrentAnimatorStateInfo(m_LayerIndex).length;

            m_StateMachine.defaultState = m_SrcState;
            m_Transition.mute           = false;
            AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, m_Controller);
            m_AvatarPreview.Animator.Update(0.00001f);
            WriteParametersInController();
            m_AvatarPreview.Animator.SetLayerWeight(m_LayerIndex, 1);

            float currentStateDuration = m_AvatarPreview.Animator.GetCurrentAnimatorStateInfo(m_LayerIndex).length;

            if (m_LayerIndex > 0)
            {
                m_AvatarPreview.Animator.stabilizeFeet = false;
            }
            float maxDuration = (currentStateDuration * m_RefTransition.exitTime) + (m_Transition.duration * (m_RefTransition.hasFixedDuration ? 1.0f : currentStateDuration)) + nextStateDuration;

            // case 546812 disable previewer if the duration is too big, otherwise it hang Unity. 2000.0f is an arbitrary choice, it can be increase if needed.
            // in some case we got a m_Transition.duration == Infinity, bail out before unity hang.
            if (maxDuration > 2000.0f)
            {
                Debug.LogWarning("Transition duration is longer than 2000 second, Disabling previewer.");
                m_ValidTransition = false;
                m_IsResampling    = false;
                return;
            }

            float effectiveCurrentStatetime = m_RefTransition.exitTime > 0 ? currentStateDuration * m_RefTransition.exitTime : currentStateDuration;
            // We want 30 samples/sec, maxed at 300 sample for very long state, and very short animation like 1 frame should at least get 5 sample
            float currentStateStepTime = effectiveCurrentStatetime > 0 ? Mathf.Min(Mathf.Max(effectiveCurrentStatetime / 300.0f, 1.0f / 30.0f), effectiveCurrentStatetime / 5.0f) :  1.0f / 30.0f;
            float nextStateStepTime    = nextStateDuration > 0 ? Mathf.Min(Mathf.Max(nextStateDuration / 300.0f, 1.0f / 30.0f), nextStateDuration / 5.0f) : 1.0f / 30.0f;

            currentStateStepTime = Mathf.Max(currentStateStepTime, maxDuration / 600.0f);
            nextStateStepTime    = Mathf.Max(nextStateStepTime, maxDuration / 600.0f);

            float stepTime = currentStateStepTime;

            float currentTime = 0.0f;

            bool hasStarted      = false;
            bool hasTransitioned = false;
            bool hasFinished     = false;

            //For transitions with exit time == 0, skip to end of clip so transition happens on first frame
            if (m_RefTransition.exitTime == 0)
            {
                m_AvatarPreview.Animator.CrossFade(0, 0f, 0, 0.9f);
            }
            m_AvatarPreview.Animator.StartRecording(-1);

            m_AvatarPreview.Animator.Update(0.0f);
            AnimatorStateInfo currentState = m_AvatarPreview.Animator.GetCurrentAnimatorStateInfo(m_LayerIndex);

            m_LeftStateWeightA = currentState.normalizedTime;
            m_LeftStateTimeA   = currentTime;
            while (!hasFinished && currentTime < maxDuration)
            {
                m_AvatarPreview.Animator.Update(stepTime);

                currentState = m_AvatarPreview.Animator.GetCurrentAnimatorStateInfo(m_LayerIndex);
                currentTime += stepTime;

                if (!hasStarted)
                {
                    m_LeftStateWeightB = currentState.normalizedTime;
                    m_LeftStateTimeB   = currentTime;

                    hasStarted = true;
                }

                if (hasTransitioned && currentTime >= maxDuration)
                {
                    hasFinished = true;
                }

                if (!hasTransitioned && currentState.IsName(m_DstState.name))
                {
                    m_RightStateWeightA = currentState.normalizedTime;
                    m_RightStateTimeA   = currentTime;

                    hasTransitioned = true;
                }

                if (!hasTransitioned)
                {
                    m_LeftStateWeightB = currentState.normalizedTime;
                    m_LeftStateTimeB   = currentTime;
                }

                if (hasTransitioned)
                {
                    m_RightStateWeightB = currentState.normalizedTime;
                    m_RightStateTimeB   = currentTime;
                }

                if (m_AvatarPreview.Animator.IsInTransition(m_LayerIndex))
                {
                    stepTime = nextStateStepTime;
                }
            }

            float endTime = currentTime;

            m_AvatarPreview.Animator.StopRecording();

            if (Mathf.Approximately(m_LeftStateWeightB, m_LeftStateWeightA) || Mathf.Approximately(m_RightStateWeightB, m_RightStateWeightA))
            {
                Debug.LogWarning("Difference in effective length between states is too big. Transition preview will be disabled.");
                m_ValidTransition = false;
                m_IsResampling    = false;
                return;
            }

            float leftDuration  = (m_LeftStateTimeB - m_LeftStateTimeA) / (m_LeftStateWeightB - m_LeftStateWeightA);
            float rightDuration = (m_RightStateTimeB - m_RightStateTimeA) / (m_RightStateWeightB - m_RightStateWeightA);

            if (m_MustSampleMotions)
            {
                // Do this as infrequently as possible
                m_MustSampleMotions = false;
                m_SrcPivotList.Clear();
                m_DstPivotList.Clear();

                stepTime = nextStateStepTime;
                m_StateMachine.defaultState = m_DstState;
                m_Transition.mute           = true;
                AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, m_Controller);
                m_AvatarPreview.Animator.Update(0.0f);
                m_AvatarPreview.Animator.SetLayerWeight(m_LayerIndex, 1);
                m_AvatarPreview.Animator.Update(0.0000001f);
                WriteParametersInController();
                currentTime = 0.0f;
                while (currentTime <= rightDuration)
                {
                    TimelineControl.PivotSample sample = new TimelineControl.PivotSample();
                    sample.m_Time   = currentTime;
                    sample.m_Weight = m_AvatarPreview.Animator.pivotWeight;
                    m_DstPivotList.Add(sample);
                    m_AvatarPreview.Animator.Update(stepTime * 2);
                    currentTime += stepTime * 2;
                }

                stepTime = currentStateStepTime;
                m_StateMachine.defaultState = m_SrcState;
                m_Transition.mute           = true;
                AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, m_Controller);
                m_AvatarPreview.Animator.Update(0.0000001f);
                WriteParametersInController();
                m_AvatarPreview.Animator.SetLayerWeight(m_LayerIndex, 1);
                currentTime = 0.0f;
                while (currentTime <= leftDuration)
                {
                    TimelineControl.PivotSample sample = new TimelineControl.PivotSample();
                    sample.m_Time   = currentTime;
                    sample.m_Weight = m_AvatarPreview.Animator.pivotWeight;
                    m_SrcPivotList.Add(sample);
                    m_AvatarPreview.Animator.Update(stepTime * 2);
                    currentTime += stepTime * 2;
                }

                m_Transition.mute = false;
                AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, m_Controller);
                m_AvatarPreview.Animator.Update(0.0000001f);
                WriteParametersInController();
            }

            m_Timeline.StopTime = m_AvatarPreview.timeControl.stopTime = endTime;
            m_AvatarPreview.timeControl.currentTime = m_Timeline.Time;
            if (resetTimeSettings)
            {
                m_Timeline.Time = m_Timeline.StartTime = m_AvatarPreview.timeControl.currentTime = m_AvatarPreview.timeControl.startTime = 0;
                m_Timeline.ResetRange();
            }

            m_AvatarPreview.Animator.StartPlayback();

            m_AvatarPreview.Animator.playbackTime = 0f;
            m_AvatarPreview.Animator.Update(0f);
            m_AvatarPreview.ResetPreviewFocus();

            m_IsResampling = false;
        }