Forum rules - please read before posting.

Custom Hotspot that orients on arrival?

AFAICT, while a Hotspot2D can have a Walk-to Marker associated with it, there is not a property you can set to orient the player using the Marker's rotation rotation on arrival (unless I missed it...). You can add this behavior by adding to the Interactions of the Hotspot, but I would prefer not to have to manually add that via the GUI for every Hotspot2D in my game.

Intuitively, I feel like I should be able to create my own Prefab that is derived from HotSpot2D that makes this behavior the default, and then I should be able to simply use instances of MyCustomHotspot2D instead of the built-in HotSpot2D, right?

In the Start() method of MyCustomHotspot2D.cs, I tried registering events for both OnHotspotReach and OnCharacterReachNode. The contract of OnHotspotReach seems easier to work with for my purposes, but my Debug.Log() statement is never getting printed when I click on my Hotspot2D and the character walks to the Marker.

I do see my Debug.Log() statement for OnCharacterReachNode get printed, but the signature is a bit fussy because I have to take the Paths path and int node and determine whether it matches the walkToMarker of the Hotspot belonging to my Hotspot2D.

Questions:

  • Am I correct that, without subclassing, there is no way to make Turn To Face the default without adding an interaction?
  • Assuming subclassing is the best way for me to change the defaults for a custom component, does Create > Prefab Variant using Hotspot2D seem to be the right way to go about it?
  • Should OnHotspotReach be firing and is that the event I should be linking my logic to?

Thanks so much for your help!

Comments

  • With help from ChatGPT, this seems to work, though that < 0.1f is a bit dissatisfying.

    using AC;
    using UnityEngine;
    
    public class MyCustomHotspot2D: MonoBehaviour
    {
        private Hotspot hotspot;
        private Marker markerForHotspot;
    
        void Start()
        {
            hotspot = GetComponent<Hotspot>();
            if (hotspot != null)
            {
                Marker walkToMarker = hotspot.walkToMarker;
                if (walkToMarker != null)
                {
                    this.markerForHotspot = walkToMarker;           
                }
                else
                {
                    Debug.LogWarning("MyCustomHotspot2Dshould have a walkToMarker");
                }
            }
            else
            {
                Debug.LogWarning("MyCustomHotspot2Dshould have a Hotspot component");
            }
    
            EventManager.OnCharacterReachNode += OnCharacterReachNode;
        }
    
        private void OnDestroy()
        {
            EventManager.OnCharacterReachNode -= OnCharacterReachNode;
        }
    
        private void OnCharacterReachNode(AC.Char character, Paths path, int node)
        {
            if (character == KickStarter.player && markerForHotspot != null && Vector3.Distance(path.nodes[node], markerForHotspot.transform.position) < 0.1f)
            {
                KickStarter.player.SetRotation(markerForHotspot.Rotation);
            }
        }
    
        // Update is called once per frame
        void Update()
        {
    
        }
    }
    
    
  • Welcome to the community, @bolinfest.

    Am I correct that, without subclassing, there is no way to make Turn To Face the default without adding an interaction?

    Checking Face after moving? in the Hotspot's Interaction panel should cause the Player to face the same direction as the Walk-to Marker upon reaching it. Is that option not displaying? It should show for both the Walk To Marker and Walk To Player action options.

    Assuming subclassing is the best way for me to change the defaults for a custom component, does Create > Prefab Variant using Hotspot2D seem to be the right way to go about it?

    Your script doesn't specifically subclass the Hotspot, but the default Hotspot2D prefab is more of a convenience than a requirement - it's simply a Hotspot component attached to a 2D Collider. A custom prefab can either be a variant of a fresh one.

    It's a somewhat hidden feature of AC, but it is possible to register custom prefabs in the Scene Manager so that they appear in the prefabs panel at the bottom. To do this, view the Scene Manager asset file in Debug mode, and then fill in the prefab's details in the Scene Manager Prefab Datas array.

    Should OnHotspotReach be firing and is that the event I should be linking my logic to?

    OnHotspotReach should be firing at the expected time. What's your AC version, and can you share screenshots of both your Settings Manager, and the Hotspot's Inspector? I'll attempt a recreation of the issue.

  • @ChrisIceBox sorry for the slow reply!

    I don't see something named Face after moving?, but I assume you are asking whether I can perform these two steps through the GUI:

    • add an interaction for Hotspot2D by hitting the plus button (for Use interactions and/or Examine interaction)
    • choose Turn To Face from the dropdown

    Yes, I can do that, but when I say I want to make it the default, I mean that I don't want to have to go through the GUI to set these options every time I add a hotspot. That is: I want every hotspot in my game to behave this way with few exceptions.

    In general, I prefer to manage change through code and source control over GUIs and mysterious files. So to achieve what I'm trying to do here, is what I have done (created a prefab variant and attached a script), the right thing to do?

  • I'm trying to give you a minimal repro for my issue with OnHotspotReach. I feel like the easiest thing to do would be to make a modification to the demo game, but I don't know how to iterate on it quickly: every time I press the Play button for the Park scene, I have to sit through the entire credits. I assume there's some sort of shortcut to skip them, but I don't know what it is.

    Going back to my example above, here is what I think is a minimal repro:

    using AC;
    using UnityEngine;
    
    public class MyCustomHotspot2D: MonoBehaviour
    {
        void Start()
        {
            EventManager.OnHotspotReach += OnHotspotReached;
        }
    
        private void OnHotspotReached(Hotspot hotspot, AC.Button button)
        {
            Debug.Log("Player has reached the Hotspot: " + hotspot.name);
        }
    
    }
    

    If I attach this script to my scene, I never see that debug line get printed. This is with v1.81.6 on Windows.

  • Upgraded to 1.81.7 and I still see the same issue.

  • Taking a step backwards, how does a hotspot have to be configured such that OnHotspotReach is triggered? That is, does the Hotspot have to have a Walk-to Marker associated with it? And does arriving at that marker trigger OnHotspotReach? That is what I have been assuming, but again, I have not been able to get the event to fire.

  • Based on https://adventurecreator.org/forum/discussion/15511/doing-text-based-development-using-ac-as-the-engine-more-like-scumm/, I think the reason OnHotspotReach wasn't firing is because playerAction = PlayerAction.WalkToMarker also needs to be set in code somewhere, which seems to happen under the hood when you go through the GUI to configure the action.

  • I think the reason OnHotspotReach wasn't firing is because playerAction = PlayerAction.WalkToMarker also needs to be set in code somewhere, which seems to happen under the hood when you go through the GUI to configure the action.

    That's essentially it. If, in the Hotspot's Use interaction panel, you have Player action set to Turn To Face, then the Player will not "reach" any Marker in the sense that they are not walking over to it.

    The Face after moving? option will show if the above is instead set to Walk To Marker. To be clear: does setting these options as such - in the UI - give you the intended behaviour?

    This data isn't part of the Hotspot prefab, because a Hotspot has no Interactions by default. If you want to set this up through code, you can do so by attaching a custom component that alters this at runtime:

    using UnityEngine;
    using AC;
    
    public class SetHotspotWalkTo : MonoBehaviour
    {
    
        void Awake ()
        {
            Hotspot hotspot = GetComponent<Hotspot> ();
            var button = hotspot.GetFirstUseButton ();
            if (button != null)
            {
                button.playerAction = PlayerAction.WalkToMarker;
                button.faceAfter = true;
            }
        }
    
    }
    
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.