Forum rules - please read before posting.

Floating Icons on Hotspot!

I don't know if it's a good title for what I need .The game is in point and click style, camera from above most of the time. Context sensitive interaction. I have a lot of drawers and metal cabinets in which there are some objects that the player will examine or pick up. The idea is that when the player approaches and opens a drawer or cabinet, icons will pop up presenting objects that I can examine or pick up and move to the inventory. For this, I made a menu with elements that can be turned on or off as needed via the action list. The problem is that with the increase in objects, this will be very fast overcrowded with actions! Is there any way this could be done cleaner? Maybe some better solution?

Comments

  • edited November 2024

    You can configure the automated display of icons above Hotspots in the "Hotspots" section of the Settings Manager.

    You'll need to make sure your Hotspots have a Highlight component attached and assigned, however.

  • Sorry for not being more clear. I have made when I click on a hotspot, for example a closet (locker), a certain animation action goes through which the player opens it and then through the menu, icons will pop up across the screen presenting the objects that the player will pick up in the inventory!

    This approach would be used in other, similar scenes where the player finds something and picks it up

    I made menu and button elements for each icon with action list to move to inventory and with certain icons states to show and hide menu elements. Is this good approach or there's some better solution for this?

    example what I did:
    https://drive.google.com/file/d/1s2J1v2bEqdeD-Tm4Ng7G4mXkXhhYFmcw/view?usp=sharing

    action list on first locker
    https://drive.google.com/file/d/1qWUewumFPmn7Suihxx56ciFCL1FxCuw-/view?usp=sharing

  • If the icons represent Inventory items, then you can rely on a Container object + Menu to let the Player click them to transfer to their own Inventory.

    Use the Scene Manager to create a new Container, assign the Items you want it to hold, and open it when clicking the Hotspot with the Container: Open Action.

    The default interface includes a Container menu that will display these items, which you can configure to appear/behave as your current example does.

  • I was just looking for something like that! Thanks Chris :)

  • edited December 2024

    I didn't want to open a new topic.
    Is there a way to do something similar, as a container for objects that I would like to inspect and examine?
    Let's say: notes, documents, photos. So some kind of menu that opens when hotspot is clicked and icons appear that I can click to examine them!
    I also thought of some idea as an menu inventory to be able to change icons, but I'm not sure how to set this up. Do you have any suggestions or ideas?

  • Sorry, I need more detail on what you're after - can you elaborate, ideally with screenshots/mockups?

    If the icons you're looking to show are interaction types (look, use etc), then you can use an Interaction menu - see the 2D Demo as an example.

  • The idea is that when I want to examine an object (a table or a drawer, when I click on the hotspot, a menu with images (Items) appears, perhaps something similar to a container, but instead of clicking on an icon (button image) to transfer to the inventory, a new menu opens with a short description and image. I think the document inventory and menu can serve here (it has a picture and a short description)

    Image of the idea:

    https://drive.google.com/file/d/1tHCeB8FS_KX9_deW4536uw_SaWagohBF/view?usp=sharing

    Video of what I have so far but a little sloppy

    https://drive.google.com/file/d/1H0bXixSz1EbMK8KkSU2WK9Gbh4OEFMz2/view?usp=sharing

    On the video I have a script that is not the best solution, but it can explain what I mean exactly. When I click on the hotspot, a new menu opens, in this case a panel (UI) with icons (buttons) which, when clicked, open the AC document via the event. That would be exactly what I would need.

    I wonder if I could do this over the AC? Is there a more elegant solution with AC?

  • A hybrid approach of AC + a simple custom script is likely the best way.

    Firstly, you'll want to store any data that gets displayed for a given Item as part of that Item itself.

    For example, if you want to show a description, create a new Inventory string Property named Description. Each Item can then assign a unique value for this property. If you only want specific Items to have this data, you can use Inventory Categories to filter them.

    You'll want to stick with Containers, only with Click behaviour set to Custom Script so that clicking items doesn't move them to the Player's Inventory.

    Your custom script can then listen out for the OnMouseOverMenu custom event, extract the item that was clicked, and update the Menu accordingly.

    Something along the lines of:

    void OnMenuElementClick (Menu menu, MenuElement element, int slot, int buttonPressed)
    {
        if (menu.title == "Menu1" && element.title == "Items")
        {
            MenuInventoryBox inventoryBox = element as MenuInventoryBox;
            InvInstance clickedInstance = inventoryBox.GetInstance (slot);
            if (!InvInstance.IsValid (clickedInstance)) return;
    
            string descriptionText = clickedInstance.GetProperty ("Description").TextValue;
    
            MenuLabel label = PlayerMenus.GetElementWithName ("Menu2", "Description") as MenuLabel;
            label.OverrideLabel (descriptionText);
        }
    }
    
  • Hey Chris, I think I succeeded :) This was quite a challenge, but I wonder if it's possible to do all this through one "main" container and not create a new menu? Here I had to lock the main container menu so it wouldn't interfere with the other menu (menu1) when it's on.
    It would be nice to have everything in one "main" container. Let's say category1 of inventory items on click goes to inventory and category2 is for displaying details in the second menu
    Here's the video of what I made so far:

    https://drive.google.com/file/d/1331SrmUyAE6qG04SReNRi5Ehjj6CApcG/view?usp=sharing

    I'm just wondering how I could turn off the label of the inventory items so that it is not visible in second (details) menu? It seems somehow too messy to me. But I would like that only for some specific items ( maybe in category) not all.

    I like the option for properties and categories, I think it's very useful.

    Maybe I would make one suggestion, let's say you add the "check category" option to the inventory list action. I think it would be useful in certain situations when I want to isolate everything from that category. For now, there is an option: Check and Check selected, but that's only for a specific item, not for a group.
    Thus, in some situations, I could check whether the entire category is in the inventory or in the container, and if it is not, then a specific action would be performed.
    Also, you could add another option to the container action like the close option. For now there are: add or remove, check and open .
    In my case, that option could be used instead of locking main container menu. Whenever I close the menu (menu1), the action goes to close the main container menu as well..
    just a suggestion, thanks anyway

  • What's the underlying issue preventing you from currently using the same Container menu for both situations? If it's a case of the two Menus having different properties, you can adjust these at runtime through code - see this tutorial for details.

    Thus, in some situations, I could check whether the entire category is in the inventory or in the container, and if it is not, then a specific action would be performed.

    I'm not clear on your intent. Is it to check if all items within a given category are within the Inventory?

    It's a bit of a specific case, but it could certainly be done within a custom Action.

  • edited December 2024

    Yes, it's two menus but after several attempts I just replaced a few things and named it and it works in one container! Save and load work in the editor and build. I also added a small notification that the item has been picked up in the inventory with an animated menu. The only thing is that I haven't tried switching to a new scene yet, although I don't see any reason why it shouldn't work.
    Video of action:
    https://drive.google.com/file/d/1RrK9MnjY7sf-xAu8qfIMKJcHDMwDdx51/view?usp=sharing

    That's what I meant. To check if all items in given category are within the inventory.
    You are right! It's a little specific case and I did it through a custom script, but somehow I was thinking there would be a more elegant solution inside the action list.

  • You are right! It's a little specific case and I did it through a custom script, but somehow I was thinking there would be a more elegant solution inside the action list.

    If you've already written a custom script function that makes your intended check - i.e. a function that returns a bool value - share it here and I can help convert it into a custom "check" Action.

  • edited December 2024

    Sure Chris! Here it is. Although I have corrected this a little according to my needs. Maybe you could put in adventure wikia if someone needs it

    When specific categories are checked ,you can run different actions depending: if condition are met or not met

    The script:

    using UnityEngine;
    using System.Collections.Generic;

    if UNITY_EDITOR

    using UnityEditor;

    endif

    namespace AC
    {
    [System.Serializable]
    public class ActionCheckInventoryCategory : Action
    {
    // Declare properties here
    public int categoryID = 0; // Category ID to check
    public ActionListAsset ifConditionMet;
    public ActionListAsset ifConditionNotMet;

        public override ActionCategory Category { get { return ActionCategory.Custom; } }
        public override string Title { get { return "Check Inventory Category"; } }
        public override string Description { get { return "Checks if all items in a specified category are in the inventory and runs different actions based on the result."; } }
    
        // Declare variables here
        public override float Run()
        {
            if (!isRunning)
            {
                isRunning = true;
                bool result = AreAllItemsInCategoryInInventory(categoryID);
    
                // Log the result for debugging
                Debug.Log($"All items in category {categoryID} are in inventory: {result}");
    
                // Run corresponding action list
                if (result && ifConditionMet != null)
                {
                    ifConditionMet.Interact();
                }
                else if (!result && ifConditionNotMet != null)
                {
                    ifConditionNotMet.Interact();
                }
    
                // Set the action complete
                isRunning = false;
                return 0f;
            }
    
            return 0f;
        }
    
        // Function to check inventory
        private bool AreAllItemsInCategoryInInventory(int categoryID)
        {
            // Get all items in the inventory
            List<InvItem> inventory = KickStarter.runtimeInventory.localItems;
    
            // Get all items in the specified category
            List<InvItem> categoryItems = KickStarter.inventoryManager.items.FindAll(item => item.binID == categoryID);
    
            // Check if each category item is in the player's inventory
            foreach (InvItem categoryItem in categoryItems)
            {
                if (!inventory.Exists(invItem => invItem.id == categoryItem.id))
                {
                    return false; // Found an item in the category that is not in the inventory
                }
            }
    
            return true; // All items in the category are in the inventory
        }
    

    if UNITY_EDITOR

        public override void ShowGUI()
        {
            // Action-specific Inspector GUI code here
            categoryID = EditorGUILayout.IntField("Category ID to check:", categoryID);
            ifConditionMet = (ActionListAsset)EditorGUILayout.ObjectField("If condition met:", ifConditionMet, typeof(ActionListAsset), false);
            ifConditionNotMet = (ActionListAsset)EditorGUILayout.ObjectField("If condition not met:", ifConditionNotMet, typeof(ActionListAsset), false);
        }
    
        public override string SetLabel()
        {
            // Return a string used to describe the specific action's job.
            return $"Check Category {categoryID}";
        }
    

    endif

    }
    

    }

  • This should do it:

    using UnityEngine;
    using System.Collections.Generic;
    #if UNITY_EDITOR
    using UnityEditor;
    #endif
    
    namespace AC
    {
    
        [System.Serializable]
        public class ActionCheckInventoryCategory : ActionCheck
        {
    
            public int categoryID = 0; // Category ID to check
    
            public override ActionCategory Category { get { return ActionCategory.Custom; } }
            public override string Title { get { return "Check Inventory Category"; } }
            public override string Description { get { return "Checks if all items in a specified category are in the inventory and runs different actions based on the result."; } }
    
    
            public override bool CheckCondition ()
            {
                return AreAllItemsInCategoryInInventory(categoryID);
            }
    
            // Function to check inventory
            private bool AreAllItemsInCategoryInInventory(int categoryID)
            {
                // Get all items in the inventory
                List<InvItem> inventory = KickStarter.runtimeInventory.localItems;
    
                // Get all items in the specified category
                List<InvItem> categoryItems = KickStarter.inventoryManager.items.FindAll(item => item.binID == categoryID);
    
                // Check if each category item is in the player's inventory
                foreach (InvItem categoryItem in categoryItems)
                {
                    if (!inventory.Exists(invItem => invItem.id == categoryItem.id))
                    {
                        return false; // Found an item in the category that is not in the inventory
                    }
                }
                return true; // All items in the category are in the inventory
            }
    
            #if UNITY_EDITOR
    
            public override void ShowGUI ()
            {
                categoryID = EditorGUILayout.IntField("Category ID to check:", categoryID);
            }
    
            public override string SetLabel ()
            {
                return $"Check Category {categoryID}";
            }
    
            #endif
    
        }
    
    }
    
  • Great! Thanks Chris :)

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.