Forum rules - please read before posting.

Hotspot advice

edited September 2021 in Technical Q&A

Looking for advice on my specific use of hotspots on NPCs. The prefab instance in the scene looks like this:

And I have attached this script to each hotspot object so it will always face the camera when the character turns:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FixPosition : MonoBehaviour {

    Transform t;
    public float fixedRotation = 5;

    void Start () {
        t = transform;
    }

    void Update () {
        t.eulerAngles = new Vector3 (t.eulerAngles.x, fixedRotation, t.eulerAngles.z);

    }
}

And to each hotspot object, I have also attached the MultiLimitHotspotCamera script so that each set of hotspots will be automatically turned on or off depending on where the player is (the NPC is a companion that follows the player around).

This seems to work reasonably well in the editor, but MultiLimitHotspotCamera is hiding the hotspot when it shouldn't in the build. I'm currently using this version of the script:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using AC;

public class MultiLimitHotspotCamera : MonoBehaviour
{

    [SerializeField] private Hotspot hotspot;
    [SerializeField] private List<_Camera> limitToCameras = new List<_Camera>();

    private void OnEnable ()
    {
        EventManager.OnSwitchCamera += SwitchCamera;
    }

    private void OnDisable ()
    {
        EventManager.OnSwitchCamera -= SwitchCamera;
    }

    private void SwitchCamera (_Camera old, _Camera newCamera, float transitionTime)
    {
        if (limitToCameras.Contains (newCamera))
        {
            hotspot.limitToCamera = newCamera;
        }
    }

}

Any idea why this would be happening?

Something else that I've noticed is that the cameras selected aren't saved in the prefab, only in the scene. Would it be possible to save the cameras selected by ConstantID so this solution would work across scenes?

Comments

  • What's the reason for needing two Hotspots? I'm not following how the camera relates to whether or not the NPC should be interactive, either. Could you share screenshots to illustrate the situation?

    I have attached this script to each hotspot object so it will always face the camera when the character turns

    This shouldn't be necessary. You can either parent the Hotspots to your sprite child, or uncheck Turn root object in 3D? in the NPC Inspector to avoid the need for counter-rotation.

    This seems to work reasonably well in the editor, but MultiLimitHotspotCamera is hiding the hotspot when it shouldn't in the build.

    Where is the script attached, and how are you switching camera?

    I can't see why you'd be getting a difference between Editor and build, but if you want it to work across scenes then you'll need to change the script anyway to detect cameras in a different way.

    One approach would be to rely on Tags - i.e. giving each camera a specific Tag based on whether or not you wanted it to make the NPC interactive at that moment:

    using UnityEngine;
    using AC;
    
    public class LimitHotspotCameraByTag : MonoBehaviour
    {
    
        [SerializeField] private Hotspot hotspot;
        [SerializeField] private string limitToTag;
    
        private void OnEnable () { EventManager.OnSwitchCamera += SwitchCamera; }
        private void OnDisable () { EventManager.OnSwitchCamera -= SwitchCamera; }
    
        private void SwitchCamera (_Camera old, _Camera newCamera, float transitionTime)
        {
            if (newCamera.gameObject.CompareTag (limitToTag))
            {
                hotspot.limitToCamera = newCamera;
            }
        }
    
    }
    
  • edited September 2021

    Thanks, Chris! I think the tag would work really well in some cases, but the inability to have multiple tags in a single gameobject sadly makes this impossible for me. So I was giving it some thought, and I figured out my requirements and a possible way to achieve them (currently can't be achieved with AC but bear with me):

    My game is a 2D, side-scrolling one where different cameras delimit separate spaces in the scene. So I have the main zoomed out, sidescrolling camera that follows the player as they walk along a street. When they click to enter a house, the camera zooms in and then fades into a fixed camera where the house façade's layer is no longer rendered, so you can see inside the house. Each floor of the house has one camera like this, so limiting hotspots to those cameras is a very easy way to manage STATIONARY hotsposts. I've got this working perfectly.

    The problem I'm trying to solve is what to do with NPCs that can walk in and out of those different spaces.

    Requirements:

    1. An NPC's hotspot children should only be interactive when the NPC is in the same "space" as the player.

    2. This interactivity should not be the same as simply turning the hotspot on and off (i.e. a hotspot that is OFF when the NPC is in a different space should not be turned on just because the NPC entered that space; conversely, a hotspot that is ON should not be interactive in a different space, but should become interactive when the NPC enters the same space). This is possible, right? Limiting a hotspot to a camera has a similar effect.

    Possible solution:

    1. Set up different triggers over separate spaces (they do not overlap in 2D space, and I've already had success doing this to change footstep sounds according to the type of surface being walked on). Number those spaces.

    2. Add an int component variable to the player and each NPC.

    3. When the player or NPC enters a trigger, their gameobject will be received as a parameter.

    4. (Need help with this) An action will compare the gameobject parameter with a gameobject or prefab. For example, trigger #3 needs to do this: IF parameter == NPC #1, then change their component variable to 3. I would need to set up a series of if statements for every character in the scene.

    5. (Need help with this) A script will compare each NPC's component variable to the player's own variable, and then make their children hotsposts interactive ONLY when the integers match. As advised earlier, I've made the hotsposts children of the NPC's sprite.

  • If you limit a Hotspot to a separate Camera (e.g. "DummyCamera") that isn't actually used, it won't be interactive but will still be considered "on" by the save system. One trick would be to set this camera in the Hotspot's limitToCamera field whenever you want it to be non-interactive.

    Alternatively, you can assign an Interactive Boundary to a Hotspot, which is like a Trigger for the Player that automatically sets a Hotspot's interactable state. It might be feasible to have an NPC Hotspot update their own Interactive Boundary as they leave/enter a house.

    Can you share screens that illustrate the situation? It's a visual problem, so it's important to be clear on the exact situation.

  • edited September 2021
    1. Street camera (follows horizontally)

    1. Garden camera

    1. Floor 1 camera

    Daniel follows the player in and out of places, but when he is not following, he also has his own schedule where he walks to different places independently of where the player is. Every other NPC has a schedule, so I need a solution where an NPC outside the house won't display their hotspots if the player is inside, and vice-versa.

    You are absolutely right that we can just use triggers + changing the limitToCamera field! That would be very good since I'm already using cameras to manage the stationary hotspots like doors, light switches, etc.

    So basically, all I need is:

    (1) An action to check if the character that entered a trigger is a given character; then, if it returns true:
    (2) An action to change a hotspot's limitToCamera field.

  • You needn't rely on custom Actions - a custom script attached to the Trigger itself can listen out for the OnRunTrigger custom event and process the character there:

    using UnityEngine;
    using AC;
    
    public class LimitToCameraTrigger : MonoBehaviour
    {
    
        public string characterName;
        public _Camera limitToCamera;
    
        private void OnEnable () { EventManager.OnRunTrigger += OnRunTrigger; }
        private void OnDisable () { EventManager.OnRunTrigger -= OnRunTrigger; }
    
        private void OnRunTrigger (AC_Trigger trigger, GameObject collidingObject)
        {
            if (trigger.gameObject == gameObject && characterName == collidingObject.name)
            {
                Hotspot[] npcHotspots = collidingObject.GetComponentsInChildren<Hotspot>();
                foreach (Hotspot npcHotspot in npcHotspots)
                {
                    npcHotspot.limitToCamera = limitToCamera;
                }
            }
        }
    }
    

    As a side-note: you may want to convert any NPCs that follow the Player to uncontrollable Player characters - see this tutorial. This makes it much easier to control/manage the state of such characters across multiple scenes.

  • edited September 2021

    You needn't rely on custom Actions - a custom script attached to the Trigger itself can listen out for the OnRunTrigger custom event and process the character there:

    Thank you! I've just tested it and it works well for the most part. I've noticed a glitch though: if the trigger/script sets an NPC's hotspot's limitToCamera field to camera #1, and then we switch from camera #2 to camera #1, the hotspost becomes interactive as expected. However, if the main camera was always camera #1 to begin with, and then the hotspot's limitToCamera field is set to camera #1, the hotspot doesn't become interactive. It only works if we switch away from camera #1 and then back again. It's like the visibility check only runs on camera switch, not on limitToCamera field switch.

    As a side-note: you may want to convert any NPCs that follow the Player to uncontrollable Player characters - see this tutorial. This makes it much easier to control/manage the state of such characters across multiple scenes.

    I considered doing this, but I think it will be of limited use to me because the NPC followers are supposed to follow a schedule when they are not following the player (even when they are off scene), so saving the location where they were left behind won't reflect their true location after a couple of minutes. I've figured out a way to account for their positions moving off-scene though, so I'm good in that regard.

  • However, if the main camera was always camera #1 to begin with, and then the hotspot's limitToCamera field is set to camera #1, the hotspot doesn't become interactive.

    I'll attempt a recreation.

    NPC followers are supposed to follow a schedule when they are not following the player (even when they are off scene)

    FWIW, the "Player: Teleport inactive" Action can be used to change an inactive Player's position in unopen scenes.

  • Recreated - I shall issue a fix in v1.74.3.

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.