Forum rules - please read before posting.

Drag and drop inventory items with a controller

So I've been setting my inventory to be able to combine items by dragging and dropping. I set the inventory settings like this:

For each inventory item, I removed the "Use" action list and put it in "Examine" instead. It seems that with the settings I have, clicking on the inventory item works as usual, but I can still drag and drop them. This works fine with the mouse. I also want it to work with a controller. I can have one item selected, hold the A button, select another, and release. It will work. But there's nothing visually indicating I'm dragging the item. I would like it show the cursor just like with the mouse, so that it's clear I'm holding the item.

And is there a way to assign the Drag and drop to another input with the controller? So that selecting the item is still A but drag and drop is used with X?

Comments

  • What are your AC and Unity versions?

    But there's nothing visually indicating I'm dragging the item. I would like it show the cursor just like with the mouse, so that it's clear I'm holding the item.

    The cursor should change its appearance regardless of your input method. When using a controller, are you navigating Menus directly, or moving a simulated cursor with the controller's L-stick?

    If you're navigating the Menu directly, the cursor isn't involved. One way around this would be to show the currently-selected item in a separate InventoryBox menu element that has its Inventory box type property set to Display Selected.

    And is there a way to assign the Drag and drop to another input with the controller? So that selecting the item is still A but drag and drop is used with X?

    You can run an item's Examine interaction by pressing a button linked to an input named "InteractionB". If you want to prevent the ability to Examine an item by pressing/releasing "InteractionA", as is the case now, you'd need to uncheck Can drop an Item onto itself to Examine it? and Clicking an Item without dragging Examines it? in the Settings Manager.

    If you wanted to make this dynamic (i.e. changed at runtime), you can modify these through script - just right-click each field's label to get an API reference to it. You can use this script on the AC wiki to change your "Input method" dynamically:

    https://adventure-creator.fandom.com/wiki/Switching_input_method_dynamically

    However, I'd recommend first tweaking the settings manually in the Editor to get things behaving with a controller alone first, before attempting to have the settings change based on what input is currently used.

  • My AC version is 1.74.2. Unity is 2019.4.23f1.

    I'm navigating menus directly. I tried adding a new InventoryBox set to Display Selected. How can I get the currently selected inventory item's screen position? I was thinking I could write a script to move this new object to the currently selected item's position. Also, one thing I noticed is that whenever I dragged the inventory item over itself, the currently selected image changed to the items "Selected" texture, but it should remain in the "Main" one. Is there a way around that?. By the way, I'm using a Unity Ui prefab.

    Is there a way for me to have it so Examining the item is done with InteractionA and selecting it is done with Interaction B? Examining would be the main thing players would do in the game, so it's better if it's mapped to InteractionA. I noticed that the setting only appeared if I unchecked Drag and drop inventory interface. Is there no way to do it with that enabled?

  • I'm navigating menus directly. I tried adding a new InventoryBox set to Display Selected. How can I get the currently selected inventory item's screen position? I was thinking I could write a script to move this new object to the currently selected item's position.

    Working with Unity UI RectTransform positions can be very tricky, but AC provides a function that lets you get the screen-space position of a given element's slot. Here's a script that gets this for the currently-selected item in the default Inventory menu (i.e. using the default menu/element naming convention):

    using UnityEngine;
    using AC;
    
    public class SelectedItemPositioner : MonoBehaviour
    {
    
        private void Update ()
        {
            Menu menu = PlayerMenus.GetMenuWithName ("Inventory");
            MenuInventoryBox inventoryBox = menu.GetElementWithName ("InventoryBox") as MenuInventoryBox;
    
            for (int i = 0; i < inventoryBox.GetNumSlots (); i++)
            {
                InvInstance invInstance = inventoryBox.GetInstance (i);
                if (InvInstance.IsValid (invInstance) && invInstance == KickStarter.runtimeInventory.SelectedInstance)
                {
                    Vector2 slotPosition = menu.GetSlotCentre (inventoryBox, i);
                    Debug.Log ("Selected item position: " + slotPosition;
                    // Update selected item prefab's position based on slotPosition
                    break;
                }
            }
        }
    
    }
    

    You'd need to extend it by using the slotPosition value to update the "Display Selected" RectTransform position, but check that the value showing in the Console is correct first.

    Also, one thing I noticed is that whenever I dragged the inventory item over itself, the currently selected image changed to the items "Selected" texture, but it should remain in the "Main" one. Is there a way around that?.

    Can you share screenshots of both the issue occuring, and of the Settings / Inventory Manager field values that cause this? It may be possible to change these dynamically when an item is hovered over itself.

    Is there a way for me to have it so Examining the item is done with InteractionA and selecting it is done with Interaction B? Examining would be the main thing players would do in the game, so it's better if it's mapped to InteractionA.

    It's possible to override the reading of inputs by overriding delegates in the PlayerInput component - see the Manual's "Remapping inputs" chapter for details on this topic.

    As an example, this script will swap the reading of "InteractionA" and "InteractionB" button-downs when the "Inventory" menu is open:

    using UnityEngine;
    using AC;
    
    public class InputOverride : MonoBehaviour
    {
    
        void Start ()
        {
            KickStarter.playerInput.InputGetButtonDownDelegate = My_InputGetButtonDown;
        }
    
        private bool My_InputGetButtonDown (string inputAxis)
        {
            if (PlayerMenus.GetMenuWithName ("Inventory").IsOn ())
            {
                if (inputAxis == "InteractionA")
                {
                    return Input.GetButtonDown ("InteractionB");
                }
                if (inputAxis == "InteractionB")
                {
                    return Input.GetButtonDown ("InteractionA");
                }
            }
            try
            {
                return Input.GetButtonDown (inputAxis);
            }
            catch {}
        }
    
    }
    

    Things get a little more complex if you're using Unity UI, however, since that relies on the EventSystem's "Submit" field instead of InteractionA. You'd have to update the EventSystem.current's Submit field value at the correct time as well (e.g. when the Inventory menu is turned on/off).

    I noticed that the setting only appeared if I unchecked Drag and drop inventory interface. Is there no way to do it with that enabled?

    Settings are hidden if they will have no effect based on the values of others. Which setting is hiding, and what are you trying to achieve with it?

  • edited January 2023

    Hey. So I managed to do all of these another way with a custom script. But I ran into some issues. If I click and hold anywhere outside of any inventory button, and drag on top of an inventory item, it will count as selecting that inventory item. This should not happen. If I don't click on an inventory item, it shouldn't count as me selecting it. Also, if I drag an inventory item and drop it on nothing to cancel the interaction, KickStarter.runtimeInventory.SelectedItem isn't cleared. So if I select another inventory item, it will still have the other inventory item selected.
    Here is a video showing the issues.

    Here's my script:
    public class InventoryCurrentlySelected : MonoBehaviour
    {
    public RawImage image;
    GVar usingGamepad;
    public GameObject useTextGroup;
    public TextMeshProUGUI use;
    public TextMeshProUGUI item1;
    public TextMeshProUGUI on;
    public TextMeshProUGUI item2;

            void Start()
            {
                usingGamepad = GlobalVariables.GetVariable(3);
                useTextGroup.SetActive(false);
            }
    
            void Update()
            {
                InvItem selectedItem = KickStarter.runtimeInventory.SelectedItem;
                InvItem hoverItem = KickStarter.runtimeInventory.hoverItem;
                if (selectedItem == null)
                {
                    // If there is no selected item, hide the image and return
                    image.enabled = false;
                    useTextGroup.SetActive(false);
                    return;
                }
                image.enabled = true;
                image.texture = selectedItem.activeTex;
                // Set the image's position to the selected item's position
    
                if (usingGamepad.BooleanValue == true)
                {
                    Vector2 itemPosition = EventSystem.current.currentSelectedGameObject.transform.position;
                    transform.position = itemPosition;
                }
                else
                {
                    //limit the cursor's position to the inventory bounds
                    transform.position = new Vector2(Mouse.current.position.ReadValue().x, Mathf.Clamp(Mouse.current.position.ReadValue().y, 0, Screen.height * 0.1f));
                }
                if (hoverItem != null)
                {
                    useTextGroup.SetActive(true);
                    if (selectedItem == hoverItem)
                    {
                        on.gameObject.SetActive(false);
                        item2.gameObject.SetActive(false);
                    }
                    else
                    {
                        on.gameObject.SetActive(true);
                        item2.gameObject.SetActive(true);
                    }
                    item1.text = selectedItem.label;
                    item2.text = KickStarter.runtimeInventory.hoverItem.label;
    
                }
                else
                {
                    useTextGroup.SetActive(false);
                }
    
            }
        }
    

    Sorry about the formatting. I don't know how to properly include the whole script in code formatting.

    I'm having these issues with my custom script. But I tested without it and using AC's built in features and they also happen.

  • For code to appear correctly, just make sure that each line has at least one tab-indent.

    The script itself doesn't deal with the selection/deselection of items, however - only the updating of UI based on that.

    What are your AC/Unity versions now, and can you share steps that produce the selection issues? Ideally, changes to AC's Demo game + Managers, as this would be the most reliable way to recreate such issues on both ends.

  • Unity version is 2019.4.23f1. AC version is v1.74.2. The issue still happens even if I turn off my script and I enable the inventory cursor.
    Here are some images of my settings:


    The steps to replicate the issues are:
    1. Click and hold on an inventory item.
    2. Release on an empty space on the inventory.
    3. Click and hold on an empty space on the inventory.
    4. The cursor will change and selected item will change to the previously selected item.

    I added some debugging lines to my script using KickStarter.runtimeInventory.SelectedItem and it is cleared whenever I let go of the click. But when I click again, it changes to the previously selected item.

    The other issue is:
    1. Click and hold on an empty space in the inventory.
    2. Bring the cursor on top of one of the inventory items.
    3. The inventory item will be selected, as if I had clicked it, when nothing should have happened.

    This is the Button component on one of the buttons:

  • After doing some testing, I found that it might have something to do with my InputActions. If I use the defaultInputActions found in Unity, the first issue no longer happens.



  • The presence of Input System is an important detail. How does the "Submit" section of your Default Input Actions asset compare with your own?

  • It has only the Submit[Any].

  • Thanks for the details - I'll attempt a recreation.

  • I've updated the Input System integration with definitions for mouse-clicking within the Controls asset's InteractionA asset.

    If you import the new package, and uncheck Mouse clicks have default functionality? in the Settings Manager, then the input detected from InteractionA should be enough for drag-and-drop. Try this without the Submit button input - on my end, it's enough to get it working.

  • Thanks! But how do I do that?

  • In a backup/duplicate project, import the new InputSystem integration package from AC's Downloads page and revert back to the provided Controls asset. You should find that it then has mouse input added to its InteractionA input definition.

    Uncheck Mouse clicks have default functionality? under your Settings Manager's "Interface settings" panel, and AC should then rely on InteractionA for dragging and dropping.

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.