Adventure Creator Wikia
Advertisement

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.

Advertisement