Simultaneous Hotspot labels

This script allows you to display multiple Hotspot labels at the same time - either always during gameplay, or when the Hotspot is highlighted.  It works by making a copy of the Hotspot menu defined in the Menu Manager.

It is particularly useful when working with Touch Screen input in conjunction with Player Vicinity hotspot detection, since that involves nearby Hotspots highlighting without becoming selected.

First, create a Hotspot menu (or modify the default one) with both an **Appear type** and **Position** of **On Hotspot**.  To prevent it showing up normally as well, also check **Start game locked off?** (our copies will be unlocked through script).

To have it display at all times during gameplay, check **Always Show During Gameplay** in the component's Inspector. Otherwise, you will need to define a Highlight component for each Hotspot.  If you don't want the Highlight to have a visible effect on any mesh, uncheck **Auto-brighten materials?**.

Create a new C# script named **MultiHotspotLabel**, and attach it to each Hotspot GameObject:

```
using UnityEngine;
using AC;

public class MultiHotspotLabel : MonoBehaviour
{

 public Hotspot hotspotToShow;
 public Highlight highlightToSync;
 public bool alwaysShowDuringGameplay;
 public LayerMask layerMask = new LayerMask ();

 public string menuName = "Hotspot"; // The name of the Hotspot Menu to copy
 public string labelName = "HotspotLabel"; // The Label element of the Hotspot Menu
 private Menu myMenu; // Our own local Menu

 private void OnEnable ()
 {
 // Attempt to auto-assign components if not set yet
 if (hotspotToShow == null)
 {
 hotspotToShow = GetComponent<Hotspot> ();
 }
 if (highlightToSync == null && hotspotToShow != null)
 {
 highlightToSync = hotspotToShow.highlight;
 }

 if (alwaysShowDuringGameplay)
 {
 EventManager.OnEnterGameState += OnEnterGameState;
 return;
 }

 // Add our own listeners to the Highlight component's onHighlightOn and onHighlightOff events
 if (highlightToSync != null)
 {
 highlightToSync.callEvents = true;
 highlightToSync.onHighlightOn.AddListener (ShowForHotspot);
 highlightToSync.onHighlightOff.AddListener (Hide);
 }
 }

 private void Start ()
 {
 if (alwaysShowDuringGameplay)
 {
 ShowForHotspot ();
 }
 }

 private void OnEnterGameState (GameState gameState)
 {
 switch (gameState)
 {
 case GameState.Normal:
 ShowForHotspot ();
 break;

 default:
 Hide ();
 break;
 }
 }

 private void OnDisable ()
 {
 if (alwaysShowDuringGameplay)
 {
 EventManager.OnEnterGameState -= OnEnterGameState;
 Hide ();
 return;
 }

 // Remove our own listeners from the Highlight component's onHighlightOn and onHighlightOff events
 if (highlightToSync != null)
 {
 highlightToSync.onHighlightOn.RemoveListener (ShowForHotspot);
 highlightToSync.onHighlightOff.RemoveListener (Hide);
 }
 }

 private void Update ()
 {
 if (myMenu)myMenu.HotspotLabelData.SetData (hotspotToShow, string.Empty);

 if (hotspotToShow != null && alwaysShowDuringGameplay && KickStarter.stateHandler.IsInGameplay ())
 {
 if (hotspotToShow.limitToCamera != null && KickStarter.mainCamera.attachedCamera != hotspotToShow.limitToCamera)
 {
 // Turn off
 Hide ();
 return;
 }

 Vector3 direction = hotspotToShow.GetIconPosition () - Camera.main.transform.position;
 Ray ray = new Ray (Camera.main.transform.position, direction);
 RaycastHit hitInfo = new RaycastHit ();
 if (Physics.Raycast (ray, out hitInfo, direction.magnitude, layerMask.value))
 {
 if (hitInfo.collider.gameObject != hotspotToShow.gameObject)
 {
 // Turn off
 Hide ();
 return;
 }
 }

 ShowForHotspot ();
 }
 }

 private void ShowForHotspot ()
 {
 // Call this function to show a new Menu linked to the given Hotspot
 if (myMenu == null)
 {
 // When run for the first time, create a new Menu and use the default Hotspot menu to copy from
 Menu menuToCopy = PlayerMenus.GetMenuWithName (menuName);
 if (menuToCopy == null)
 {
 ACDebug.LogWarning ("Cannot find menu with name '" + menuName + "'", this);
 return;
 }
 myMenu = ScriptableObject.CreateInstance<Menu> ();

 myMenu.CreateDuplicate (menuToCopy); // Copy from the default Menu
 myMenu.appearType = AppearType.Manual; // Set it to Manual so that we can control it easily
 myMenu.isLocked = false; // Unlock it so that the default can remain locked if necessary
 myMenu.title += this.name;
 myMenu.SetHotspot (hotspotToShow, null); // Link it to the Hotspot

 if (!string.IsNullOrEmpty (labelName))
 {
 (myMenu.GetElementWithName (labelName) as MenuLabel).labelType = AC\_LabelType.Normal;
 (myMenu.GetElementWithName (labelName) as MenuLabel).label = hotspotToShow.GetName (Options.GetLanguage ());
 }
 }

 // Turn the menu on
 myMenu.TurnOn ();

 // Register with PlayerMenus to handle updating
 KickStarter.playerMenus.RegisterCustomMenu (myMenu, true);
 }

 private void Hide ()
 {
 // Call this function to hide the Menu
 if (myMenu != null)
 {
 if (KickStarter.eventManager)
 {
 myMenu.TurnOff ();
 }
 myMenu = null;
 }
 }

}

```

In its component Inspector (or by modifying the script), set the **Menu Name** value to the name of the Hotspot Menu listed in your Menu Manager that should be copied each time. The **Hotspot To Show** and **Highlight To Sync** values will also need to be assigned, but this is automatic if these components are already on the same GameObject as the above script.

When the game runs, the script will automatically add its own functions to the Highlight component's custom events.