aboutsummaryrefslogtreecommitdiff
path: root/JamHelper/Assets/Scripts/Smooth-Motion-in-Unity/InterpolationObjectController.cs
blob: 9a83fe063fcfddc959bab37df359e69bf9d841d1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
using System.Collections;
using UnityEngine;

[DisallowMultipleComponent]
[DefaultExecutionOrder(ORDER_EXECUTION)]
public class InterpolationObjectController : MonoBehaviour
{
    public const int ORDER_EXECUTION = InterpolationFactorController.ORDER_EXECUTION - 1;

    private TransformData[] _transforms;
    private int _index;

    private void Awake()
    {
        StartCoroutine(WaitForEndOfFrame());
        StartCoroutine(WaitForFixedUpdate());
    }

    private void OnEnable()
    {
        ResetTransforms();
    }

    private void BeforeFixedUpdate()
    {
        // Restoring actual transform for the FixedUpdate() cal where it could be change by the user.
        RestoreActualTransform();
    }

    private void AfterFixedUpdate()
    {
        // Saving actual transform for being restored in the BeforeFixedUpdate() method.
        SaveActualTransform();
    }

    private void Update()
    {
        // Set interpolated transform for being rendered.
        SetInterpolatedTransform();
    }

    #region Helpers

    private void RestoreActualTransform()
    {
        var latest = _transforms[_index];
        transform.localPosition = latest.position;
        transform.localScale = latest.scale;
        transform.localRotation = latest.rotation;
    }

    private void SaveActualTransform()
    {
        _index = NextIndex();
        _transforms[_index] = CurrentTransformData();
    }

    private void SetInterpolatedTransform()
    {
        var prev = _transforms[NextIndex()];
        float factor = InterpolationFactorController.Factor;
        transform.localPosition = Vector3.Lerp(prev.position, transform.localPosition, factor);
        transform.localRotation = Quaternion.Slerp(prev.rotation, transform.localRotation, factor);
        transform.localScale = Vector3.Lerp(prev.scale, transform.localScale, factor);
    }

    public void ResetTransforms()
    {
        _index = 0;
        var td = CurrentTransformData();
        _transforms = new TransformData[2] { td, td };
    }

    private TransformData CurrentTransformData()
    {
        return new TransformData(transform.localPosition, transform.localRotation, transform.localScale);
    }

    private int NextIndex()
    {
        return (_index == 0) ? 1 : 0;
    }

    private IEnumerator WaitForEndOfFrame()
    {
        while (true)
        {
            yield return new WaitForEndOfFrame();
            BeforeFixedUpdate();
        }
    }

    private IEnumerator WaitForFixedUpdate()
    {
        while (true)
        {
            yield return new WaitForFixedUpdate();
            AfterFixedUpdate();
        }
    }

    private struct TransformData
    {
        public Vector3 position;
        public Quaternion rotation;
        public Vector3 scale;

        public TransformData(Vector3 position, Quaternion rotation, Vector3 scale)
        {
            this.position = position;
            this.rotation = rotation;
            this.scale = scale;
        }
    }

    #endregion
}