SkeletonAnimationFixedTimestep.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /******************************************************************************
  2. * Spine Runtimes License Agreement
  3. * Last updated January 1, 2020. Replaces all prior versions.
  4. *
  5. * Copyright (c) 2013-2020, Esoteric Software LLC
  6. *
  7. * Integration of the Spine Runtimes into software or otherwise creating
  8. * derivative works of the Spine Runtimes is permitted under the terms and
  9. * conditions of Section 2 of the Spine Editor License Agreement:
  10. * http://esotericsoftware.com/spine-editor-license
  11. *
  12. * Otherwise, it is permitted to integrate the Spine Runtimes into software
  13. * or otherwise create derivative works of the Spine Runtimes (collectively,
  14. * "Products"), provided that each user of the Products must obtain their own
  15. * Spine Editor license and redistribution of the Products in any form must
  16. * include this license and copyright notice.
  17. *
  18. * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
  19. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
  24. * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  27. * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. *****************************************************************************/
  29. using UnityEngine;
  30. namespace Spine.Unity {
  31. // To use this example component, add it to your SkeletonAnimation Spine GameObject.
  32. // This component will disable that SkeletonAnimation component to prevent it from calling its own Update and LateUpdate methods.
  33. [DisallowMultipleComponent]
  34. public sealed class SkeletonAnimationFixedTimestep : MonoBehaviour {
  35. #region Inspector
  36. public SkeletonAnimation skeletonAnimation;
  37. [Tooltip("The duration of each frame in seconds. For 12 fps: enter '1/12' in the Unity inspector.")]
  38. public float frameDeltaTime = 1 / 15f;
  39. [Header("Advanced")]
  40. [Tooltip("The maximum number of fixed timesteps. If the game framerate drops below the If the framerate is consistently faster than the limited frames, this does nothing.")]
  41. public int maxFrameSkip = 4;
  42. [Tooltip("If enabled, the Skeleton mesh will be updated only on the same frame when the animation and skeleton are updated. Disable this or call SkeletonAnimation.LateUpdate yourself if you are modifying the Skeleton using other components that don't run in the same fixed timestep.")]
  43. public bool frameskipMeshUpdate = true;
  44. [Tooltip("This is the amount the internal accumulator starts with. Set it to some fraction of your frame delta time if you want to stagger updates between multiple skeletons.")]
  45. public float timeOffset;
  46. #endregion
  47. float accumulatedTime = 0;
  48. bool requiresNewMesh;
  49. void OnValidate () {
  50. skeletonAnimation = GetComponent<SkeletonAnimation>();
  51. if (frameDeltaTime <= 0) frameDeltaTime = 1 / 60f;
  52. if (maxFrameSkip < 1) maxFrameSkip = 1;
  53. }
  54. void Awake () {
  55. requiresNewMesh = true;
  56. accumulatedTime = timeOffset;
  57. }
  58. void Update () {
  59. if (skeletonAnimation.enabled)
  60. skeletonAnimation.enabled = false;
  61. accumulatedTime += Time.deltaTime;
  62. float frames = 0;
  63. while (accumulatedTime >= frameDeltaTime) {
  64. frames++;
  65. if (frames > maxFrameSkip) break;
  66. accumulatedTime -= frameDeltaTime;
  67. }
  68. if (frames > 0) {
  69. skeletonAnimation.Update(frames * frameDeltaTime);
  70. requiresNewMesh = true;
  71. }
  72. }
  73. void LateUpdate () {
  74. if (frameskipMeshUpdate && !requiresNewMesh) return;
  75. skeletonAnimation.LateUpdate();
  76. requiresNewMesh = false;
  77. }
  78. }
  79. }