コード例 #1
0
ファイル: MeshAnimator.cs プロジェクト: RistoSK/Firekeeper
 private void OnEnable()
 {
     mTransform = transform;
     if (resetOnEnable && meshFilter)
     {
         if (playAutomatically)
         {
             Play(defaultAnimation.name);
         }
         else
         {
             isPaused = true;
         }
         if (currentAnimation != null)
         {
             currentAnimation.GenerateFrameIfNeeded(baseMesh, currentFrame);
             currentAnimation.DisplayFrame(meshFilter, currentFrame, -1);
         }
     }
     MeshAnimatorManager.AddAnimator(this);
     lastFrameTime = Time.time;
 }
コード例 #2
0
ファイル: MeshAnimator.cs プロジェクト: dawid621/MeshAnimator
        public void UpdateTick(float time)
        {
            if (initialized == false)
            {
                return;
            }
            MeshAnimation cAnim = currentAnimation;

            if ((isVisible == false && updateWhenOffscreen == false) || isPaused || speed == 0 || cAnim.playbackSpeed == 0)             // return if offscreen or crossfading
            {
                return;
            }
            // if the speed is below the normal playback speed, wait until the next frame can display
            float lodFPS      = LODLevels.Length > currentLodLevel ? LODLevels[currentLodLevel].fps : FPS;
            float totalSpeed  = Mathf.Abs(cAnim.playbackSpeed * speed);
            float tickRate    = Mathf.Max(0.0001f, 1f / lodFPS / totalSpeed);
            float actualDelta = time - lastFrameTime;
            bool  finished    = false;

            float pingPongMult = pingPong ? -1 : 1;

            if (speed * cAnim.playbackSpeed < 0)
            {
                currentAnimTime -= actualDelta * pingPongMult * totalSpeed;
            }
            else
            {
                currentAnimTime += actualDelta * pingPongMult * totalSpeed;
            }

            if (currentAnimTime < 0)
            {
                currentAnimTime = cAnim.length;
                finished        = true;
            }
            else if (currentAnimTime > cAnim.length)
            {
                if (cAnim.wrapMode == WrapMode.Loop)
                {
                    currentAnimTime = 0;
                }
                finished = true;
            }

            nextTick      = time + tickRate;
            lastFrameTime = time;

            float normalizedTime = currentAnimTime / cAnim.length;
            int   previousFrame  = currentFrame;

            currentFrame = Mathf.Min(Mathf.RoundToInt(normalizedTime * cAnim.totalFrames), cAnim.totalFrames - 1);

            // do WrapMode.PingPong
            if (cAnim.wrapMode == WrapMode.PingPong)
            {
                if (finished)
                {
                    pingPong = !pingPong;
                }
            }

            if (finished)
            {
                bool stopUpdate = false;
                if (queuedAnims != null && queuedAnims.Count > 0)
                {
                    Play(queuedAnims.Dequeue());
                    stopUpdate = true;
                }
                else if (cAnim.wrapMode != WrapMode.Loop && cAnim.wrapMode != WrapMode.PingPong)
                {
                    nextTick   = float.MaxValue;
                    stopUpdate = true;
                }
                if (OnAnimationFinished != null)
                {
                    OnAnimationFinished(cAnim.animationName);
                }
                if (stopUpdate)
                {
                    FireAnimationEvents(cAnim, totalSpeed, finished);
                    return;
                }
            }

            // generate frames if needed and show the current animation frame
            cAnim.GenerateFrameIfNeeded(baseMesh, currentFrame);

            // if crossfading, lerp the vertices to the next frame
            if (currentCrossFade.isFading)
            {
                if (currentCrossFade.currentFrame >= currentCrossFade.framesNeeded)
                {
                    currentFrame    = 0;
                    previousFrame   = -1;
                    currentAnimTime = 0;
                    ReturnCrossfadeToPool();
                }
                else
                {
#if !THREADS_ENABLED
                    GenerateCrossfadeFrame();
#endif
                    if (currentCrossFade.generatedFrame >= currentCrossFade.currentFrame)
                    {
                        if (crossFadeMesh == null)
                        {
                            crossFadeMesh = GetCrossfadeFromPool();
                        }
                        crossFadeMesh.vertices = currentCrossFade.frame.positions;
                        crossFadeMesh.bounds   = currentCrossFade.frame.bounds;
                        if (recalculateCrossfadeNormals)
                        {
                            crossFadeMesh.RecalculateNormals();
                        }
                        meshFilter.sharedMesh = crossFadeMesh;
                        currentCrossFade.ReturnFrame();
                        currentCrossFade.currentFrame++;
                        if (currentCrossFade.currentFrame < currentCrossFade.framesNeeded)
                        {
                            EnqueueAnimatorForCrossfade(this);
                        }
                        // move exposed transforms
                        bool exposedTransforms = childMap != null;
                        bool applyRootMotion   = cAnim.rootMotionMode == MeshAnimation.RootMotionMode.AppliedToTransform;
                        if (exposedTransforms || applyRootMotion)
                        {
                            float         delta     = currentCrossFade.currentFrame / (float)currentCrossFade.framesNeeded;
                            MeshFrameData fromFrame = currentCrossFade.fromFrame;
                            MeshFrameData toFrame   = currentCrossFade.toFrame;
                            // move exposed transforms
                            if (exposedTransforms)
                            {
                                for (int i = 0; i < cAnim.exposedTransforms.Length; i++)
                                {
                                    Transform child = null;
                                    if (fromFrame.exposedTransforms.Length <= i || toFrame.exposedTransforms.Length <= i)
                                    {
                                        continue;
                                    }
                                    if (childMap != null && childMap.TryGetValue(cAnim.exposedTransforms[i], out child))
                                    {
                                        Matrix4x4 f = fromFrame.exposedTransforms[i];
                                        Matrix4x4 t = toFrame.exposedTransforms[i];
                                        Matrix4x4 c = MatrixLerp(f, t, delta);
                                        MatrixUtils.FromMatrix4x4(child, c);
                                    }
                                }
                            }
                            // apply root motion
                            if (applyRootMotion)
                            {
                                Vector3    pos = Vector3.Lerp(fromFrame.rootMotionPosition, toFrame.rootMotionPosition, delta);
                                Quaternion rot = Quaternion.Lerp(fromFrame.rootMotionRotation, toFrame.rootMotionRotation, delta);
                                transform.Translate(pos, Space.Self);
                                transform.Rotate(rot.eulerAngles * Time.deltaTime, Space.Self);
                            }
                        }
                    }
                }
            }
            if (currentCrossFade.isFading == false)
            {
                cAnim.DisplayFrame(meshFilter, currentFrame, previousFrame);
                if (currentFrame != previousFrame)
                {
                    bool exposedTransforms = childMap != null;
                    bool applyRootMotion   = cAnim.rootMotionMode == MeshAnimation.RootMotionMode.AppliedToTransform;
                    if (exposedTransforms || applyRootMotion)
                    {
                        MeshFrameData frame = cAnim.GetNearestFrame(currentFrame);
                        // move exposed transforms
                        if (exposedTransforms)
                        {
                            for (int i = 0; i < cAnim.exposedTransforms.Length; i++)
                            {
                                Transform child = null;
                                if (frame.exposedTransforms.Length > i && childMap != null && childMap.TryGetValue(cAnim.exposedTransforms[i], out child))
                                {
                                    MatrixUtils.FromMatrix4x4(child, frame.exposedTransforms[i]);
                                }
                            }
                        }
                        // apply root motion
                        if (applyRootMotion)
                        {
                            if (previousFrame > currentFrame)
                            {
                                // animation looped around, apply motion for skipped frames at the end of the animation
                                for (int i = previousFrame + 1; i < cAnim.frames.Length; i++)
                                {
                                    MeshFrameData rootFrame = cAnim.GetNearestFrame(i);
                                    transform.Translate(rootFrame.rootMotionPosition, Space.Self);
                                    transform.Rotate(rootFrame.rootMotionRotation.eulerAngles * Time.deltaTime, Space.Self);
                                }
                                // now apply motion from first frame to current frame
                                for (int i = 0; i <= currentFrame; i++)
                                {
                                    MeshFrameData rootFrame = cAnim.GetNearestFrame(i);
                                    transform.Translate(rootFrame.rootMotionPosition, Space.Self);
                                    transform.Rotate(rootFrame.rootMotionRotation.eulerAngles * Time.deltaTime, Space.Self);
                                }
                            }
                            else
                            {
                                for (int i = previousFrame + 1; i <= currentFrame; i++)
                                {
                                    MeshFrameData rootFrame = cAnim.GetNearestFrame(i);
                                    transform.Translate(rootFrame.rootMotionPosition, Space.Self);
                                    transform.Rotate(rootFrame.rootMotionRotation.eulerAngles * Time.deltaTime, Space.Self);
                                }
                            }
                        }
                    }
                }
            }
            if (OnFrameUpdated != null)
            {
                OnFrameUpdated();
            }

            FireAnimationEvents(cAnim, totalSpeed, finished);

            // update the lod level if needed
            if (LODLevels.Length > 0 && (LODCamera != null || Camera.main))
            {
                if (LODCamera == null)
                {
                    LODCamera = Camera.main.transform;
                }
                float dis      = (LODCamera.position - mTransform.position).sqrMagnitude;
                int   lodLevel = 0;
                for (int i = 0; i < LODLevels.Length; i++)
                {
                    if (dis > LODLevels[i].distance * LODLevels[i].distance)
                    {
                        lodLevel = i;
                    }
                }
                if (currentLodLevel != lodLevel)
                {
                    currentLodLevel = lodLevel;
                }
            }
        }