/// <summary>
        /// Fires when the graph for the timeline begins playing.
        /// </summary>
        public override void OnGraphStart(Playable playable)
        {
            stateDrivers = new Dictionary <Type, StateDriver>();

            PlayerCharacter player = GameManager.Player != null ? GameManager.Player : GameObject.FindObjectOfType <PlayerCharacter>(true);

            if (player == null)
            {
                return;
            }

            // Keep the player from changing animation/behavior states.
            player.FSM.Pause();

            // Take a snapshot of where the player started for the sake of potentially
            // restoring them later.
            GraphSnapshot = new PlayerSnapshot(player);

            // During mixing, the virtual snapshot is updated as needed by absolute posing and referenced by
            // relative posing.
            VirtualSnapshot = GraphSnapshot;

            Rigidbody2D rb = player.GetComponentInChildren <Rigidbody2D>(true);

            if (rb != null)
            {
                rb.gravityScale = 0;
                rb.velocity     = Vector3.zero;
            }
        }
        /// <summary>
        /// Throw the given item.
        /// </summary>
        /// <param name="carriable">The item to throw.</param>
        public void Throw(Carriable carriable)
        {
            var guide = player.GetComponentInChildren <ThrowingGuide>(true);

            if (guide.ThrowingStrength < 0.33f)
            {
                Drop(carriable);
                return;
            }


            carriable.OnThrow();

            Vector3 playerHead = new Vector3(player.transform.position.x, player.transform.position.y + player.Collider.bounds.size.y);
            Vector3 direction  = (player.GetMouseWorldPosition() - playerHead);

            direction.z = 0;
            direction   = direction.normalized;

            carriable.Physics.Velocity = direction * settings.ThrowingForce * guide.ThrowingStrength;

            // Check if object will collide w/ player. If it does, transport it through
            // character.
            if (direction.y < 0)
            {
                NudgeThrow(carriable, direction);
            }
        }
        /// <summary>
        /// Fires once the graph for the timeline stops playing.
        /// </summary>
        public override void OnGraphStop(Playable playable)
        {
            PlayerCharacter player = GameManager.Player != null ? GameManager.Player : GameObject.FindObjectOfType <PlayerCharacter>(true);

            if (player == null)
            {
                return;
            }

            Rigidbody2D rb = player.GetComponentInChildren <Rigidbody2D>(true);

            if (rb != null)
            {
                rb.gravityScale = 1;
                rb.velocity     = Vector3.zero;
            }

      #if UNITY_EDITOR
            if (Application.isPlaying)
            {
      #endif

            switch (Outro)
            {
            case OutroSetting.Resume: {
                // Bring them back to their original animation state, but keep their
                // ending position.
                GraphSnapshot.RestoreState(player);
                GraphSnapshot.RestoreCollider(player);
                GraphSnapshot.RestoreSprite(player);
                player.gameObject.SetActive(true);
                player.FSM.Resume();
                break;
            }

            case OutroSetting.Freeze: {
                // Keep the player's state exactly as is. This is meant be used for
                // situations where back-to-back timelines will be playing and you
                // need to keep the player where they are.
                GraphSnapshot.RestoreCollider(player);
                player.Physics.GravityScale = 0;
                break;
            }

            case OutroSetting.Revert: {
                // Bring them back to their original animation state and position from
                // before the timeline.
                GraphSnapshot.Restore(player);
                player.FSM.Resume();
                break;
            }
            }

      #if UNITY_EDITOR
        }

        else
        {
            // Restore transform on de-selecting the timeline asset in-editor.
            // Restore everything except state, since the player's FSM isn't running
            // at edit-time.
            GraphSnapshot.RestoreTransform(player);
            GraphSnapshot.RestoreCollider(player);
            GraphSnapshot.RestoreActive(player);
            GraphSnapshot.RestoreFacing(player);
            GraphSnapshot.RestoreSprite(player);
        }
      #endif
        }