Forum rules - please read before posting.

New Item in Inventory 'Pop', and Flash Hotspots questions

Hi, hoping I can please get some help here, I've tried myself but I'm just not cracking it:

  1. I'd like any new item that's added to the inventory bar to 'pop' ie scale up a bit quickly and then back down to normal, so the player realises something has happened. I've scoured the forums and tried adapting this AC tutorial with no luck:
    https://adventurecreator.org/tutorials/creating-you-have-found-item-window
    And also asked ChatGPT, and it seems like I'll need to change the Inventory Menu source from 'Adventure Creator' to 'Unity UI Prefab' so I can grab the individual game objects from the hierarchy to attach 'pop' scripts to, but my game breaks when I use UI Prefab and I'm not familiar enough with Unity's Canvas Prefabs yet, so I'd like to try get this to work with AC's native inventory source. I've got as far as the 'Add Inventory' event being able to run an ActionList, but can't seem to target the 'InventoryBox' element in the Inventory Menu to make it do eg a once-off scale animation. And I can't attach a script to anything as inventory items aren't GameObjects in the hierarchy. I'd also like to be able to have items removed from the inventory play a kind of 'dust' animation, but one thing at a time.

  2. I'm struggling to figure out how to Flash All HotSpots. I know the function exists in AC because it's in the AC manual, and have tried poking around in Unity's Project Settings and Input Settings, but can't seem to find any way to find that function nor how to link it to a keyboard button, or a button in the UI (if I could link a keyboard button to make all hotspots flash, then I could make a new button next to settings with 'simulator input' to mimic that, but I have no idea how to even get the function working in the first place.)

Thank you, from a tired newbie.

Comments

  • edited December 2024

    1) You wouldn't involve a new Menu for this - if you use Unity UI for your Inventory menu's Source, you can attach an Animator and a script to each of the Buttons that display items, and have an animation play if the item represented is the one that was added.

    Create an Animator component, add an empty Default state, and a separate state that handles the "pop", to each Button (the same Animator Controller can be used for each). Use a Trigger parameter named e.g. "Pop" that invokes this animation with a transition.

    Next, attach this script (PopItem.cs) to each Button, assigning the "slot index" field in the Inspector to the slot it's mapped to in your Menu's InventoryBox element:

    using UnityEngine;
    using AC;
    
    public class PopItem : MonoBehaviour
    {
    
        public int slotIndex;
        public string popTrigger;
    
        void OnEnable () { EventManager.OnInventoryAdd_Alt += OnInventoryAdd; }
        void OnDisable () { EventManager.OnInventoryAdd_Alt -= OnInventoryAdd; }
    
        private void OnInventoryAdd (InvCollection invCollection, InvInstance invInstance, int amount)
        {
            var menu = KickStarter.playerMenus.GetMenuWithCanvas (GetComponentInParent<Canvas> ();)
            var element = menu.GetElementWithGameObject (gameObject);
            var inventoryBox = element as MenuInventoryBox;
    
            int newItemSlot = inventoryBox.GetItemSlot (invInstance);
            if (newItemSlot == slotIndex)
            {
                GetComponent<Animator> ().SetTrigger (popTrigger);
            }
        }
    
    }
    

    2) Invoking an input named FlashHotspots will flash all Hotspots. Through code, you can do this manually with:

    foreach (Hotspot hotspot in KickStarter.stateHandler.Hotspots)
    {
        if (hotspot.highlight && hotspot.IsOn ())
            {
            hotspot.Flash ();
        }
    }
    
  • Hi Chris, thanks so much for the reply.

    1. This is going to be super useful when I make another game, thanks, might try Unity UI for Inventory, and that makes a lot of sense.
      For some reason in my current project, selecting Unity UI freezes things so I'm keen to keep using Adventure Creator as the Inventory source, and wondered if there was any way to get the same 'pop' effect without having to use Unity UI, I saw there was an 'Inventory Add' event but wasn't able to find a way to hook into it. No probs if this isn't possible, I'll leave it out of this project and try for the next one.

    2. Thank you. I have the same question I had in the other thread:
      https://adventurecreator.org/forum/discussion/15569/displaying-speedrun-timer-question#latest
      Just not entirely sure where to add the custom code, whether in a new script on an empty GameObject or if the script doesn't need to be attached to anything, and how in an ActionList to trigger code/script.
      Related: May I ask where in Unity's Input Manager one would find an entry for FlashHotspots, or would it more be about making a new input entry and then adding the code that calls the FlashHotspots function?

    1. Afraid not - you'd need the use of Unity UI for any custom animation. Do any error messages appear when using Unity UI?
    2. You don't need custom code if invoking the input is enough, but if you did - create a new C# script, and place the code in a custom public function. You can then attach it to a prefab and call it with the Object: Call event Action - see this tutorial for details.
  • edited December 2024

    2 - ah, thanks. Was easier than I thought! For anyone other newbies wondering how this works, in Edit > Project Settings > Input Manager, duplicate one of the axis and rename it to FlashHotspots and set a key to trigger it. Then, like me if you want a button in the eg Inventory to trigger it on mouse click, duplicate a button and set the axis to trigger FlashHotspots. That's it. Pressing on it or pressing f will briefly flash all hotspots in the scene, assuming they've been set to flash on mouse-over or similar.

  • edited January 5

    Hello Chris :)

    Happy new year !!

    I'm struggling to trigger the state of the animator's animation attached to the inventory menu button when an item is added to the inventory. At the same time, I'm trying to turn on the menu because I have 'Mouse Over' in the Appear Type for the inventory menu (I read in a forum topic to change it to 'Manual', turn it on, turn it off, then change it back to 'Mouse Over').

    The event is not triggering I don't know why.

    Thanks a lot ;)

    using System.Collections;
    using AC;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class InventoryAdd : MonoBehaviour
    {
        public int slotIndex;
    
        void OnEnable() { EventManager.OnInventoryAdd_Alt += OnInventoryAdd; }
        void OnDisable() { EventManager.OnInventoryAdd_Alt -= OnInventoryAdd; }
    
        private void OnInventoryAdd(InvCollection invCollection, InvInstance invInstance, int amount)
        {
            Debug.Log("HERE");
            var menu = KickStarter.playerMenus.GetMenuWithCanvas(GetComponentInParent<Canvas>());
            var element = menu.GetElementWithGameObject(gameObject);
            var inventoryBox = element as MenuInventoryBox;
    
            int newItemSlot = inventoryBox.GetItemSlot(invInstance);
            if (newItemSlot == slotIndex)
            {
    
                menu.appearType = AppearType.Manual;
                menu.TurnOn();
    
                LaunchePulseAndWaitTheEnd();
    
                menu.TurnOff();
                menu.appearType = AppearType.MouseOver;
    
            }
    
        }
    
        private IEnumerator LaunchePulseAndWaitTheEnd()
        {
            GetComponent<Animator>().SetTrigger("Pulse");
            GetComponent<Animator>().Play("Pulse");
    
            while (true)
            {
                AnimatorStateInfo stateInfo = GetComponent<Animator>().GetCurrentAnimatorStateInfo(0);
    
                if (stateInfo.IsName("Pulse") && stateInfo.normalizedTime >= 1.0f)
                {
                    break; 
                }
    
                yield return null;
            }
        }
    
    }
    
    

    Edit : I checked if event was subscribed and the answer is yes :

    https://ibb.co/2njscBs

  • This is the configuration of the inventory menu of my previous message :
    https://imgur.com/a/U3BstVM

  • edited January 6

    Happy new year @Kinteros!

    The main issue I can see is that you're listening to the event within the UI object itself. A UI Canvas is disabled when its Menu is turned off, meaning it's not able to listen out for the event.

    You'd need to move this script onto a separate GameObject within the scene, so that it's always enabled. Rather than referencing the Menu and slot components by GameObject, use the PlayerMenus GetMenuWithName / GetElementWIthName functions, i.e.:

        var menu = PlayerMenus.GetMenuWithName ("Inventory");
    

    and:

    var inventoryBox = menu.GetElementWithName ("InventoryBox") as MenuInventoryBox;
    int index = inventoryBox.GetItemSlot (invInstance);
    GameObject slot = inventoryBox.uiSlots[index].uiButton.gameObject;
    
  • Many thanks to you, @ChrisIceBox , for your prompt reply, which put me on the right track!

    I had to add a boolean to prevent the OnDisable from triggering before the end of the animation.

    Here's the final code in case anyone's interested :

    using System.Collections;
    using AC;
    using UnityEngine;
    
    public class InventoryAdd : MonoBehaviour
    {
    
        private Menu menu;
        private bool isProcessing = false;
    
    
        public void Start()
        {
            menu = PlayerMenus.GetMenuWithName("Inventory");
        }
    
        private void OnEnable()
        {
            EventManager.OnInventoryAdd_Alt += OnInventoryAdd;
        }
    
        private void OnDisable()
        {
            if (!isProcessing)
            {
                EventManager.OnInventoryAdd_Alt -= OnInventoryAdd;
            }
        }
    
        private void OnInventoryAdd(InvCollection invCollection, InvInstance invInstance, int amount)
        {
            if (menu != null) { 
                var inventoryBox = menu.GetElementWithName("InventoryBox") as MenuInventoryBox;
                int index = inventoryBox.GetItemSlot(invInstance);
                GameObject slot = inventoryBox.uiSlots[index].uiButton.gameObject;
    
                if (slot != null)
                {
                    StartCoroutine(LaunchePulseAndWaitTheEnd(slot.GetComponent<Animator>()));
                }
            }
    
        }
    
        private IEnumerator LaunchePulseAndWaitTheEnd(Animator animator)
        {
            menu.appearType = AppearType.Manual;
            menu.TurnOn();
    
            animator.SetTrigger("Pulse");
    
            while (true)
            {
                AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);
    
                if (stateInfo.IsName("Pulse") && stateInfo.normalizedTime >= 1.0f)
                {
                    break; 
                }
    
                yield return null;
            }
    
            menu.TurnOff();
            menu.appearType = AppearType.MouseOver;
    
            isProcessing = false;
    
            EventManager.OnInventoryAdd_Alt -= OnInventoryAdd;
        }
    
    }
    
    

    Thanks again, have a nice day !
    See you ;)

  • Hi @Kinteros , hope all well. Thanks for sharing your workings. May I ask how you used the script, please? ie, was it attached to a blank gameobject within a scene, and if so, did you create new gameobjects with the script in each scene you wanted the new inventory item pulse to appear in? And what else was involved, ie did you need to create a new animation controller or animations? How did you set up the event in the Events Editor window? Any more info to get a fuller picture would be great please, thank you.

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.