Forum rules - please read before posting.

Unintuitive hotspot activation "Cycle Multiple"

edited March 2023 in Technical Q&A

I'm seeing something that I don't think is the desired behaviour happen when using direct navigation and "Hotspot detection method" set to "Player Vicinity" and "Hotspot in vicinity".

Here's a repro to illustrate:
https://1drv.ms/u/s!Amz_vh8OYDX3vux-QAbvOqKSLj_Opg?e=Fcmfo7

  1. Play Scene1 - notice (by the Hotspot menu) that Box is the active hotspot
  2. Walk closer to the Door hotspot (using the arrow keys). While still having the box in the player's vicinity - notice that the box hotspot is still selected (even though the door is now the closer hotspot). The door doesn't get activated until the box is outside the vicinity.
  3. Set "Hotspot in vicinity" to "Nearest Only" - now the closest hotspot is correctly activated, but hotspot cycling is turned off - I suggest that the closest hotspot should automatically be activated even in "Cycle Multiple" too (like in for example Return to Monkey Island).

Comments

  • Recreated - though I'm not 100% convinced. To my mind, if you've cycled through some Hotspots, and then move, that same Hotspot should still be selected.

    You can replace the Hotspot Detector component with a subclass that handles this, however:

    using UnityEngine;
    using AC;
    
    public class DetectHotspotsAutoNearest : DetectHotspots
    {
    
        private Vector3 lastFramePosition;
        private void LateUpdate ()
        {
            if (transform.position != lastFramePosition && nearestHotspot && hotspots.Count > 1 && hotspots[selected] != nearestHotspot)
            {
                for (int i = 0; i < hotspots.Count; i++)
                {
                    if (hotspots[i] == nearestHotspot)
                    {
                        selected = i;
                    }
                }
            }
            lastFramePosition = transform.position;
        }
    
    }
    
  • edited March 2023

    You're right - walking away from a closer hotspot should not select it. After some further studying, here's a short clip that shows how Monkey Island make this feels so natural:
    https://1drv.ms/v/s!Amz_vh8OYDX3vu0bHaMaiTiM8J6Ahw?e=rdoyf9

    • They only auto-select the nearest hotspot that the player is facing
    • If a hotspot has been manually selected and it is not the nearest one (but still in the facing direction), that hotspot remains selected

    I (and I bet a lot of folks) would love for AC's vicinity selection to support this :)

  • With ACs new support for staying within the navmesh during direct movement, what I describe above seems like a great addition. Do you think it's something AC will support?

    Thanks

  • Please bear with me - I will post an alternative to the above soon.

  • edited April 2023
    I'm sorry, didn't mean to pressure you. Take all the time you need and only add it if you agree it makes sense for the platform.

    And congrats on the new release 👍
  • Try this alternative subclass - is this closer to the behaviour?

    using System.Collections.Generic;
    using UnityEngine;
    using AC;
    
    public class DetectHotspotsAutoNearest : DetectHotspots
    {
    
        private bool usedInput;
        private Vector3 lastFramePosition;
    
        protected new void OnEnable ()
        {
            EventManager.OnModifyHotspotDetectorCollection += OnModifyHotspotDetectorCollection;
            base.OnEnable ();
        }
    
        protected new void OnDisable ()
        {
            EventManager.OnModifyHotspotDetectorCollection -= OnModifyHotspotDetectorCollection;
            base.OnDisable ();
        }
    
    
        private List<Hotspot> OnModifyHotspotDetectorCollection (DetectHotspots detectHotspots, List<Hotspot> hotspots)
        {
            if (detectHotspots == this)
            {
                usedInput = false;
            }
            return hotspots;
        }
    
        private void Update ()
        {
            if (KickStarter.stateHandler && KickStarter.stateHandler.IsInGameplay () && IsActivePlayer ())
            {
                if (KickStarter.playerInput.InputGetButtonDown ("CycleHotspotsLeft") || KickStarter.playerInput.InputGetButtonDown ("CycleHotspotsRight") || KickStarter.playerInput.InputGetAxis ("CycleHotspots") > 0.1f || KickStarter.playerInput.InputGetAxis ("CycleHotspots") < -0.1f)
                {
                    usedInput = true;
                }
            }
        }
    
        private void LateUpdate ()
        {
            if (transform.position != lastFramePosition && !usedInput && hotspots.Count > 1 && IsActivePlayer ())
            {
                Hotspot bestHotspot = null;
                float bestDist = Mathf.Infinity;
                Vector2 playerForward = new Vector2 (KickStarter.player.TransformForward.x, KickStarter.player.TransformForward.z);
    
                foreach (Hotspot hotspot in hotspots)
                {
                    Vector2 relativePosition = hotspot.transform.position - transform.position;
    
                    float dotProduct = Vector2.Dot (relativePosition, playerForward);
                    if (dotProduct < 0.1f) continue;
    
                    if (relativePosition.sqrMagnitude < bestDist)
                    {
                        bestDist = relativePosition.sqrMagnitude;
                        bestHotspot = hotspot;
                    }
                }
    
                if (bestHotspot && hotspots[selected] != bestHotspot)
                {
                    for (int i = 0; i < hotspots.Count; i++)
                    {
                        if (hotspots[i] == bestHotspot)
                        {
                            selected = i;
                        }
                    }
                }
            }
    
            lastFramePosition = transform.position;
        }
    
    }
    
  • edited April 2023

    That's certainly a lot closer!

    This video shows two points that differ from how Monkey Island do it tho:
    https://1drv.ms/v/s!Amz_vh8OYDX3vu1IPhjDqy42fpav-A?e=uGbSol

    • 00:02 Box would still be selected (rather than Window) since we still haven't walked past half the width of the Box Hotspot
    • 00:06 Box would now be selected (rather than Door) since it's the closest hotspot in the direction the player is facing (it's totally correct that Door is still selected on 00:08 tho)
  • I would like to bring up this subject. @kloot can you share a template for detecting hotspots in your scene that you show as an example above?

  • I would if I could, unfortunately I gave up on that and no longer have the test project on disk.

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.