public override void Process(float sequencerTime, float playbackRate)
        {
            if (!AffectedObject)
            {
                return;
            }

            if (sequencerTime < StartTime || sequencerTime > EndTime)
            {
                return;
            }

            if (SplineOrientationMode == SplineOrientationMode.LookAtTransform && LookAtTarget == null)
            {
                throw new Exception("Spline Orientation Mode is look at object, but there is no LookAtTarget");
            }

            var sampleTime = (sequencerTime - StartTime) / ((EndTime - StartTime));

            var easingFunction = Shared.DoubleEasing.GetEasingFunctionFor(easingType);

            sampleTime = (float)easingFunction(sampleTime, 0.0, 1.0, 1.0);

            var modifiedRotation = sourceRotation;

            switch (SplineOrientationMode)
            {
            case SplineOrientationMode.LookAtTransform:
                AffectedObject.position = ObjectSpline.GetPositionOnPath(sampleTime);
                AffectedObject.LookAt(LookAtTarget, Vector3.up);
                modifiedRotation = AffectedObject.rotation;
                break;

            case SplineOrientationMode.LookAhead:
            {
                var nextNodePosition = ObjectSpline.GetPositionOnPath(Sequence.PlaybackRate > 0.0f ? sampleTime + USSequencer.SequenceUpdateRate : sampleTime - USSequencer.SequenceUpdateRate);
                var prevNodePosition = ObjectSpline.GetPositionOnPath(Sequence.PlaybackRate > 0.0f ? sampleTime - USSequencer.SequenceUpdateRate : sampleTime + USSequencer.SequenceUpdateRate);

                var prev = nextNodePosition.Equals(prevNodePosition);
                SmoothedQuaternion.SmoothValue = prev ? Quaternion.identity : Quaternion.LookRotation((nextNodePosition - prevNodePosition).normalized);

                AffectedObject.rotation = SmoothedQuaternion.SmoothValue;
                AffectedObject.position = ObjectSpline.GetPositionOnPath(sampleTime);

                modifiedRotation = AffectedObject.rotation;
                break;
            }

            case SplineOrientationMode.ManualOrientation:
                AffectedObject.position = ObjectSpline.GetPositionOnPath(sampleTime);
                break;
            }

            Shake.ShakeType          = shakeType;
            Shake.ShakeSpeedPosition = shakeSpeedPosition;
            Shake.ShakeRangePosition = shakeRangePosition;
            Shake.ShakeSpeedRotation = shakeSpeedRotation;
            Shake.ShakeRangeRotation = shakeRangeRotation;
            Shake.Process(sequencerTime, Sequence.Duration);

            // Must append the shake quat, so we maintain our look forward or look at object
            var shakeQuat = Quaternion.Euler(modifiedRotation.eulerAngles + Shake.EulerRotation);

            var min = 0.0f;
            var max = (Sequence.Duration * 0.1f);

            max = Mathf.Clamp(max, 0.1f, 1.0f);
            var shakeRatio = Mathf.Clamp(sequencerTime, min, max) / max;

            var shakePos = Vector3.Slerp(Vector3.zero, Shake.Position, shakeRatio);

            shakeQuat = Quaternion.Slerp(AffectedObject.localRotation, shakeQuat, shakeRatio);

            AffectedObject.localPosition += shakePos;

            // Just make sure we don't set this.
            if (SplineOrientationMode != SplineOrientationMode.ManualOrientation)
            {
                AffectedObject.localRotation = shakeQuat;
            }
        }