Forum rules - please read before posting.

only interact if player reached 'walk to marker' point

Sorry if this has been asked before but I can't seem to find any post about this.

I have the following situation:

  • My player is restricted to a small NavMesh.
  • I have a HotSpot2D outside of the NavMesh.
  • The HotSpot2D has a 'Walk to marker' marker also outside of the NavMesh.
  • After the player does some things (inside the small NavMesh) his NavMesh get's replaced by a bigger one in which he is able to reach the 'Walk to marker' marker that was previously out of reach.

When the player is in the small NavMesh and i click on the hotspot my player walks as close to the hotspot as possible allowed by the small NavMesh (not reachting the 'walk to marker' maker) and then starts the interaction (a dialogue).

I tried to fix this with an InteractiveBoundary2D but that disables the hotspot entirely, that's not what i want.
I also don't want to set 'Cutscene while moving?' setting because when the NavMesh is big it should behave like any other hotspot.

How can i make sure the interaction is only done when the player has actually reached the marker?

Comments

  • A Hotspot's Marker is assumed to be reachable - if the Player couldn't reach it, it'd be more common that it's due to an unwanted collision, in which case the Interaction should run once they've moved as close as they can to it.

    What's the exact behaviour you're looking for? Make it non-interactive during this time, or temporarily change the position of the Marker to something inside the NavMesh?

    If you want it to show up as an interactive object, but not run any interaction, you can create a "dummy" Use interaction that has no Interaction ActionList actually assigned. Have this enabled by default, and then disable the Interaction upon switching NavMesh with the Hotspot: Change interaction Action.

    Depending on your chosen Interaction method, you may also need to toggle the "proper" Use interaction as well - but if set to Context Sensitive, then only the first-enabled Use interaction will be accounted for.

  • Yes i think i can use "dummy" hotspots and replace (enable/disable) the dummy hotspots and real hotspots as soon as my NavMesh changes, or, like you said use the Hotspot: Change interaction action.

    I didn't really think of this solution and assumed that if i set "walk to marker" the interaction would stop if the marker couldn't be reached.

    Thanks for this solution, it will work perfectly!

  • edited February 2021

    I've got the same kind of a problem. I have six different interactions, like in old Sierra/LucasGames adventures: hand, ear, nose, mouth, etc. Also I usually have a notional guard and a notional object behind that guard. Current NavMesh doesn't allow player to walk to the object's marker, not until player has dealt with the guard. And this situaton "guard-object" can be repeated several times per level.

    Now, when the player reaches the edge of current navmesh, every interaction is run. But if the object is unreachable, I want to run some kind of a default interaction instead any of them, like speaking 'You can't reach it' for trying to get this object, smell it, eat and so on. To workaround it, I run my custom action which changes "playerAction" of the hotspot and in every interaction I check special local variable which tells if the object is reachable or not yet. But maybe it's not the best practice?

    Maybe I can edit some inner engine code? That's totally fine with me, I've already changed "PlayerInteraction.cs" to play a default "do" animation, before the player is interacting with any hotspot =). I guess there's some place in the code, where we can tell if we reached the marker or not? Maybe somewhere near the "EndPath" method? Or maybe we could tell it even before the player has started walking? Could you please guide me on it?

  • Depending on your interface settings, you can define Unhandled Interaction ActionLists in the Cursor Manager - one for each icon - that run if a Hotspot cannot be interacted in a given way.

    If a Hotspot has no interaction for a given icon, the unhandled asset should run instead.

    What are your Interface settings? Are you able to define such ActionLists?

    I've already changed "PlayerInteraction.cs" to play a default "do" animation, before the player is interacting with any hotspot

    This can likely move to a separate script that hooks into an event - if you'd like to do so, share your settings and details in a new thread and we'll see if that can be done.

  • Depending on your interface settings, you can define Unhandled Interaction ActionLists in the Cursor Manager - one for each icon - that run if a Hotspot cannot be interacted in a given way.

    I guess that's one of the ways to do it, yeah, but I'm afraid it could a bit heavy. If I have several hotspots behind the guard, then I have to assign interaction for every icon and for every hotspot when the guard is defeated? And I also want to show hotspots as active from the beginning, because I think it's rather confusing for the players if some objects became active only after certain actions.

    That's how I do it now. My interaction method is "Choose Interaction then Hotspot".

    First of all, there's an initialisation of reachability of the hotspot through custom action:

    Custom action does this:

    foreach (var useButton in HotspotToAffect.useButtons)
        useButton.playerAction = ActionToPerform;
    

    Hotspot's interaction looks like this:

    Maybe some kind of detection if hotspot's marker can be reached in one place of code in "PlayerInteraction.cs" will be more elegant solution?

    This can likely move to a separate script that hooks into an event - if you'd like to do so, share your settings and details in a new thread and we'll see if that can be done.

    Thank you! I'll create a separate topic for it.

  • edited March 2021

    Having a Marker not be accessible will more commonly be an error than intended, I feel. Either way, though, it's still necessary to rely on some form of logic processing to handle the two different states.

    In this situation, relying on the Cursor Manager's Unhandled interactions probably isn't the right way forward - because this is for a specific situation in that the Player cannot reach something, whereas the Unhandled interactions will be used for all situations that an interaction is not defined.

    The easiest way to me seems to be to duplicate your Hotspots, so that each has a "Cannot reach" variant, and then swap between the two sets as necessary. Since the "Cannot reach" variants would then only be interactive when the Player cannot reach them, you could then do without the need to check any variable, or alter the Player Action field.

    To enable/disable the Hotspot sets, you could either chain up a series of Hotspot: Enable or disable Actions following a Variable: Check Action, or do it through script:

    using UnityEngine;
    using AC;
    
    public class AutoSetHotspots : MonoBehaviour
    {
    
        public Hotspot[] accessibleHotspots = new Hotspot[0];
        public Hotspot[] inaccessibleHotspots = new Hotspot[0];
        public string localVariableName = "ouroborosBiten";
    
        private void OnEnable () { EventManager.OnVariableChange += OnVariableChange; }
        private void OnDisable () { EventManager.OnVariableChange -= OnVariableChange; }
    
        private void OnVariableChange (GVar variable)
        {
            if (variable.label == localVariableName)
            {
                if (variable.BooleanValue)
                {
                    EnableHotspots (accessibleHotspots);
                    DisableHotspots (inaccessibleHotspots);
                }
                else
                {
                    EnableHotspots (inaccessibleHotspots);
                    DisableHotspots (accessibleHotspots);
                }
            }
        }
    
        private void EnableHotspots (Hotspot[] hotspots)
        {
            foreach (Hotspot hotspot in hotspots)
            {
                hotspot.TurnOn ();
            }
        }
    
        private void DisableHotspots (Hotspot[] hotspots)
        {
            foreach (Hotspot hotspot in hotspots)
            {
                hotspot.TurnOff ();
            }
        }
    
    }
    
  • That's a good idea! Thank you, I'll give it a try!

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.