Looping 2D scenes

These scripts allow you to simulate a "looping" 2D scene, where walking past the edge of one side causes the player to appear at the other end seamlessly. It also allows for Hotspots that are near the edges to be interactive from the other side.

To use them:

1. Create your 2D scene, and have the two sides of the background extend, so that you can see the opposite end from each edge.
2. Extend the NavMesh as well, so that you can walk over each side's edge
3. Create a new C# script named LoopMovement.cs, and paste in the code below.
4. Attach it to an object in the scene, and configure its Inspector to match the left and right edge positions in the x-axis.
5. For each Hotspot that is visible on the opposite side of an edge, create a "dummy" one that appears in the same visual position but on the opposite side
6. Give that dummy Hotspot the same number of Interactions (but with no ActionLists), and set a Walk-to Marker that also appears visually in the same relative position
7. Create a new C# script named DummyHotspot, and attach it to each such "dummy" Hotspot.  Assign the "real" Hotspot that represents in its Inspector.

LoopMovement.cs:

```
using UnityEngine;

using AC;

public class LoopMovement : MonoBehaviour

{

    public float leftEdge = -2f;

    public float rightEdge = 2f;

    private void Update ()

    {

        float playerX = KickStarter.player.transform.position.x;

        if (playerX < leftEdge)

        {

            OffsetPlayerPosition (rightEdge - playerX);

        }

        else if (playerX > rightEdge)

        {

            OffsetPlayerPosition (leftEdge - playerX);

        }

    }

    private void OffsetPlayerPosition (float offsetAmount)

    {

        Vector3 newPosition = KickStarter.player.transform.position + (Vector3.right * offsetAmount);

        KickStarter.player.Teleport (newPosition);

        if (KickStarter.player.IsPathfinding ())

        {

            KickStarter.player.GetPath ().nodes [KickStarter.player.GetPath ().nodes.Count-1] += Vector3.right * offsetAmount;

            KickStarter.player.RecalculateActivePathfind ();

        }

        if (KickStarter.mainCamera.attachedCamera != null)

        {

            KickStarter.mainCamera.attachedCamera.MoveCameraInstant ();

            KickStarter.mainCamera.SnapToAttached ();

        }

    }

}

```

DummyHotspot.cs:

```
using UnityEngine;

using AC;

[RequireComponent (typeof (Hotspot))]

public class DummyHotspot : MonoBehaviour

{

    public Hotspot realHotspot;

    private Hotspot thisHotspot;

    private void OnEnable ()

    {

        thisHotspot = GetComponent <Hotspot>();

        EventManager.OnHotspotReach += OnHotspotReach;

        EventManager.OnHotspotTurnOn += OnHotspotTurnOn;

        EventManager.OnHotspotTurnOff += OnHotspotTurnOff;

        EventManager.OnHotspotSetInteractionState += OnHotspotSetInteractionState;

    }

    private void OnDisable ()

    {

        EventManager.OnHotspotReach -= OnHotspotReach;

        EventManager.OnHotspotTurnOn -= OnHotspotTurnOn;

        EventManager.OnHotspotTurnOff -= OnHotspotTurnOff;

        EventManager.OnHotspotSetInteractionState -= OnHotspotSetInteractionState;

    }

    private void OnHotspotReach (Hotspot hotspot, AC.Button button)

    {

        if (hotspot == thisHotspot)

        {

            switch (hotspot.GetButtonInteractionType (button))

            {

                case HotspotInteractionType.Use:

                    realHotspot.RunUseInteraction (button.iconID);

                    break;

                case HotspotInteractionType.Examine:

                    realHotspot.RunExamineInteraction ();

                    break;

                case HotspotInteractionType.Inventory:

                    realHotspot.RunInventoryInteraction (button.invID);

                    break;

                default:

                    break;

            }

        }

    }

    private void OnHotspotTurnOn (Hotspot hotspot)

    {

        if (hotspot == realHotspot)

        {

            thisHotspot.TurnOn ();

        }

    }

    private void OnHotspotTurnOff (Hotspot hotspot)

    {

        if (hotspot == realHotspot)

        {

            thisHotspot.TurnOff ();

        }

    }

    private void OnHotspotSetInteractionState (Hotspot hotspot, AC.Button button, bool isOn)

    {

        if (hotspot != realHotspot)

        {

            return;

        }

        AC.Button equivalentButton = null;

        switch (hotspot.GetButtonInteractionType (button))

        {

            case HotspotInteractionType.Use:

                {

                    int index = hotspot.useButtons.IndexOf (button);

                    equivalentButton = thisHotspot.useButtons[index];

                }

                break;

            case HotspotInteractionType.Examine:

                equivalentButton = thisHotspot.lookButton;

                break;

            case HotspotInteractionType.Inventory:

                {

                    int index = hotspot.invButtons.IndexOf (button);

                    equivalentButton = thisHotspot.invButtons[index];

                }

                break;

            default:

                break;

        }

        if (equivalentButton != null)

        {

            thisHotspot.SetButtonState (equivalentButton, isOn);

        }

    }

}

```