Features
3 min read

Creating Custom Hotspots

Hotspot integrations require three coordinated scripts plus a prefab.

1. Runtime Data (HotspotData)

  • Derive from Revoid.GigaSphere.Hotspots.HotspotData.
  • Mark the class [Serializable] if it lives outside an assembly definition.
  • Override the Type property; the value must match the prefab folder name under Resources/Runtime/Hotspots.
  • Set optional editor hints like iconPath in the constructor.
using Revoid.GigaSphere.Hotspots;
using UnityEngine;

[System.Serializable]
public sealed class MyHotspotData : HotspotData
{
    public AudioClip clip;
    public override string Type => "MyAudio";

    public MyHotspotData()
    {
        iconPath = "Edit/Icons/audio_hotspot";
    }
}

2. Runtime Anchor (HotspotAnchor)

  • Inherit from Revoid.GigaSphere.Hotspots.HotspotAnchor.
  • Override Initialize to cache typed data and hook up visuals or audio.
  • Override interaction methods (HandleInteractionClick, HandleInteractionBegin, HandleInteractionEnd) to drive behavior.
  • Call base.Initialize so the manager wiring remains intact.
using Revoid.GigaSphere.Controls;
using Revoid.GigaSphere.Hotspots;
using UnityEngine;

public sealed class MyHotspot : HotspotAnchor
{
    [SerializeField] private AudioSource audioSource;

    public override void Initialize(TourManager manager, HotspotData data)
    {
        base.Initialize(manager, data);
        if (Data is MyHotspotData typed && audioSource)
        {
            audioSource.clip = typed.clip;
        }
    }

    protected override void HandleInteractionClick()
    {
        base.HandleInteractionClick();
        if (audioSource?.clip == null)
            return;

        if (audioSource.isPlaying)
        {
            audioSource.Stop();
        }
        else
        {
            audioSource.Play();
        }
    }
}

3. Editor Integration (IHotspotEditor)

  • Implement Revoid.GigaSphere.Editor.IHotspotEditor in an Editor-only folder or assembly.
  • Decorate the class with [HotspotEditor(typeof(MyHotspotData))] so the authoring tools register it.
  • Use CreateHotspot to instantiate default data when the author adds the hotspot to a location.
  • Return a friendly menu name from GetMenuName.
using Revoid.GigaSphere.Editor;
using Revoid.GigaSphere.Graph;
using Revoid.GigaSphere.Hotspots;
using UnityEditor;
using UnityEngine;

[HotspotEditor(typeof(MyHotspotData))]
public sealed class MyHotspotEditor : IHotspotEditor
{
    public bool DrawDefaultInspector => true;

    public bool CanCreate() => true;

    public HotspotData CreateHotspot(Vector3 position)
    {
        return new MyHotspotData { position = position };
    }

    public string GetMenuName() => "My Audio Player";

    public void Initialize(TourGraph graph, LocationNodeData location) { }

    public bool OnInspectorGUI(HotspotData hotspot)
    {
        var typed = (MyHotspotData)hotspot;
        EditorGUI.BeginChangeCheck();
        typed.clip = (AudioClip)EditorGUILayout.ObjectField("Audio Clip", typed.clip, typeof(AudioClip), false);
        return EditorGUI.EndChangeCheck();
    }
}

4. Prefab Authoring

  1. Create a prefab under Resources/Runtime/Hotspots/MyAudio/. The folder name must equal the Type string.
  2. Add the custom anchor component and wire serialized references (audio source, button sprites, etc.).
  3. Optionally attach PrefabVersion and increment its version when making breaking prefab updates while you want to keep existing hotspot hierarchy. TourManager automatically picks the highest version when multiple candidates exist.
  4. Keep the prefab authoring scale relative to a sphere radius of 7 units; TourManager.LoadHotspots rescales at runtime using the active sphere radius so hotspots stay proportional.

Testing

  • Add the hotspot to a LocationInfo via the Tour Graph editor or the inspector.
  • Enter Play Mode and watch TourManager spawn the hotspot. If anything fails, check the console for Hotspot prefab not found for Type or missing component warnings.
  • Use the GuidedTour tooling if the hotspot participates in guided steps; the same data class will serialize there as well.