Forum rules - please read before posting.

Drag from inventory and place in scene at the position the item is being dragged to?

edited February 20 in Technical Q&A

Hello Chris and fellow AC'ers.

I always enjoy using AC for other things such as dressing games etc that also requires an inventory.
I have found several threads on dragging items from inventory that can show in the scene view - but a few question are still unanswered in regards to my needs. I'm doing all this in 2D.

1 - How can I make the item being placed at the point where i drag it to that doesn't have a pre placed hotspot in the scene?
In other words, I don't want it to spawn on a spot I define, but can be placed any random place in the scene.

2 - After the item has been dragged to the scene, I want to be able to drag the item in the scene around in the scene.
I suppose i have to spawn a draggable in the scene after the trick with dragging from the inventory and onto the scene?

3 - And lastly - lets assume that a chair has been dragged into the scene, and next a pet is being dragged onto the chair in the scene, then this triggers a new animation (ie pet sitting on the chair) - I guess I have to assign a hotspot to the chair - what do I need to assign to the pet so when it has been dragged to the scene (and if not placed on the chair yet, it can be dragged at any point onto the chair and it will start the animation? )

Any direction would be much appreciated,

Cheers

Comments

  • I believe @ACV is implementing mechanics similar to this, using a custom script that extends the "Arranging puzzle template" package over on the Downloads page. It would be worth PMing them to see if they can share any details.

  • Thanks Chris. No luck so far.
    The Arranging Puzzle template does cover a lot of the of what I need.
    However in terms of the dragging into the scene - I'm able to get drag an item onto the scene, bit it just spawns at a fixed place.
    Can i somehow spawn a marker on the dragged it, so the draggable that will be in the scene will spawn at that place?

    My second question is indeed what the arranging puzzle is about.

    Thanks,

  • edited March 3

    Do you want it to appear at a fixed Marker, or at the cursor position?

    A custom script would be necessary to spawn items into the scene. Essentially, you'd create an "Arranging puzzle piece" prefab for your item(s), and then assign that as the item's "Linked prefab" in the Inventory Manager.

    A custom script can then detect this when clicking on items in the Menu, and spawn it in at the mouse position.

    Something like:

    using UnityEngine;
    using AC;
    using AC.Downloads.ArrangingPuzzle;
    
    [DefaultExecutionOrder (-1)]
    public class InventoryPrefabSpawner : MonoBehaviour
    {
    
        public string menuName = "Inventory";
        public string elementName = "Items";
        public ArrangingPuzzleManager arrangingPuzzleManager;
        public bool removeSpawnedItems;
    
        void OnEnable () { EventManager.OnMenuElementClick += OnMenuElementClick; }
        void OnDisable () { EventManager.OnMenuElementClick -= OnMenuElementClick; }
    
        void OnMenuElementClick (Menu menu, MenuElement element, int slot, int buttonPressed)
        {
            if (KickStarter.runtimeInventory.SelectedItem != null) return;
    
            if (menu.title == menuName && element.title == elementName)
            {
                MenuInventoryBox inventoryBox = element as MenuInventoryBox;
                InvInstance clickedInstance = inventoryBox.GetInstance (slot);
                if (!InvInstance.IsValid (clickedInstance)) return;
    
                GameObject prefab = clickedInstance.InvItem.linkedPrefab;
                if (prefab == null) return;
    
                if (removeSpawnedItems)
                {
                    KickStarter.runtimeInventory.PlayerInvCollection.Delete (clickedInstance, 1);
                }
    
                SpawnLinkedPrefabAtMousePosition (prefab);
                KickStarter.playerInput.ResetClick ();
            }
        }
    
        private void SpawnLinkedPrefabAtMousePosition (GameObject prefab)
        {
            Vector3 spawnPosition = GetMouseWorldPosition ();
    
            GameObject spawnedPiece = Instantiate (prefab, spawnPosition, Quaternion.identity);
            ArrangingPuzzlePiece puzzlePiece = spawnedPiece.GetComponent<ArrangingPuzzlePiece> ();
    
            puzzlePiece.Initialise (arrangingPuzzleManager, null, null);
            KickStarter.runtimeInventory.SetNull ();
    
            puzzlePiece.Select ();
        }
    
        private Vector3 GetMouseWorldPosition ()
        {
            Vector3 mousePosition = KickStarter.playerInput.GetMousePosition ();
            mousePosition.z = Mathf.Abs(Camera.main.transform.position.z);
            return Camera.main.ScreenToWorldPoint(mousePosition);
        }
    
    }
    
  • edited March 1

    Thanks Chris,

    Yep, position of mousecurser/Touch release

    I have set up a prefab "Arranging Puzzle Item" with the Arranging Puzzle Manager Script on prefab level and placed the sprite as a child with the Arranging Puzzle Script, Hotspot, remember Arranging Puzzle Piece and a collider. Basically the same setup as the example included in the Arranging Puzzle prefab.
    In the inventory, I have setup the item and liked to that new prefab i created.

    I get the following compile errors:
    https://imgur.com/a/b0pv7kh

    Any idea what could cause it?

  • I've amended the script above - try it now.

  • edited March 2

    Thanks a bunch Chris.
    A few issues I'm cuious about:

    1- I tested a little, and it seems that I can only spawn the item if I already have placed puzzle item prefab in the scene hierarchy. (Outside of the camera view) - do I have to do what will all items for it to work?
    I can keep clicking on the item in the menu and it keeps cloning even if the inventory amount has been set to 1. Can I void that?

    2 - When I click the item in the inventory, it will spawn right under the menu since that is where the mousecurser is. I can't drag it into the scene and drop it at a random location that I click. Can I get it to do that?

    3 - I used the same components on my prefab as the jigsaw puzzle. I can't however the piece "freely" as the jigsaw, but the item goes back to stating position similar to the ball puzzle. How can I avoid that?

    Thanks for the great help as always. Much appreciated.
    Dan

  • edited March 3

    I've updated once more with some tweaks.

    Items should be spawned in - they won't need to be in the scene beforehand. In the case of the Blue ball from the Example scene, make it a prefab, create a "Blue ball" item and assign the prefab as its "Linked prefab".

    Couple of things to bear in mind:

    • Attach this script to the Arranging Puzzle Manager object in the scene, and assign it in the Inspector
    • Set your Inventory element's Inventory box type field to Custom Script
    • Uncheck Revert Position When Release in the Manager component to prevent snapping back
    • Because pieces are spawned in at runtime, you'll need to extend the script to have it assign each piece's "correct" Hotspot at the time it's spawned in. Let's focus on getting the spawning behaviour working first, however.
  • edited March 3

    The spawning behavior is working and I can now drag and release items into the scene.
    How awesome!

    2 Questions in regards to the spawning behavior:
    If I set the quantity to 1 in the inventory it seems to igonore that?
    Is it possible to make a minimum drag distance, so if player click/tap the icon it doesn't spawn on behind the the menu bar on the exact spot as the item is position in the inventory, but have to pull it outside the menu first?

    I'm ready to assign correct hotspots.

    Thank you so much for for even taking your time for this. Much much appreciated.

    Best,
    Dan

  • Best to get everything else sorted before moving on.

    If I set the quantity to 1 in the inventory it seems to igonore that?

    Ignore it how? That's what I've been testing with.

    Is it possible to make a minimum drag distance, so if player click/tap the icon it doesn't spawn on behind the the menu bar on the exact spot as the item is position in the inventory, but have to pull it outside the menu first?

    Tricky. Is your Inventory menu like the default, i.e. placed at the top and set to turn off when the mouse leaves it?

  • edited March 4

    Good point.

    Sorry for not being precise - With ignore I mean even if I have set the quatity to 1 of the specific item, I can can keep clicking /dragging endless amount of the item into the scene.

    In regards to the menu, its always on. I'm using the scene from the arranging puzzle with the default menu background being transparent so I can see the item being spawned behind the menu.

  • Sorry for not being precise - With ignore I mean even if I have set the quatity to 1 of the specific item, I can can keep clicking /dragging endless amount of the item into the scene.

    Check Remove Spawned Item in the Inspector to remove items that you click on.

    In regards to the menu, its always on. I'm using the scene from the arranging puzzle with the default menu background being transparent so I can see the item being spawned behind the menu.

    Positioned at the top? Try this:

    using UnityEngine;
    using AC;
    using AC.Downloads.ArrangingPuzzle;
    
    [DefaultExecutionOrder (-1)]
    public class InventoryPrefabSpawner : MonoBehaviour
    {
    
        public string menuName = "Inventory";
        public string elementName = "Items";
        public ArrangingPuzzleManager arrangingPuzzleManager;
        public float mouseYThreshold = 0.87f;
        public bool removeSpawnedItems;
        private InvInstance clickedInstance;
    
        void OnEnable () { EventManager.OnMenuElementClick += OnMenuElementClick; }
        void OnDisable () { EventManager.OnMenuElementClick -= OnMenuElementClick; }
    
        void Update ()
        {
            var mousePosition = KickStarter.playerInput.GetMousePosition ();
            float mouseY = mousePosition.y / ACScreen.height;
            if (mouseY < mouseYThreshold)
            {
                SpawnClickedItem ();
            }
        }
    
        void OnMenuElementClick (Menu menu, MenuElement element, int slot, int buttonPressed)
        {
            clickedInstance = null;
            if (KickStarter.runtimeInventory.SelectedItem != null) return;
    
            if (menu.title == menuName && element.title == elementName)
            {
                MenuInventoryBox inventoryBox = element as MenuInventoryBox;
                clickedInstance = inventoryBox.GetInstance (slot);
            }
        }
    
        private void SpawnClickedItem ()
        {
            if (!InvInstance.IsValid (clickedInstance)) return;
    
            GameObject prefab = clickedInstance.InvItem.linkedPrefab;
            if (prefab == null) return;
    
            if (removeSpawnedItems)
            {
                KickStarter.runtimeInventory.PlayerInvCollection.Delete (clickedInstance, 1);
            }
    
            SpawnLinkedPrefabAtMousePosition (prefab);
            KickStarter.playerInput.ResetClick ();
            clickedInstance = null;
        }
    
        private void SpawnLinkedPrefabAtMousePosition (GameObject prefab)
        {
            Vector3 spawnPosition = GetMouseWorldPosition ();
    
            GameObject spawnedPiece = Instantiate (prefab, spawnPosition, Quaternion.identity);
            ArrangingPuzzlePiece puzzlePiece = spawnedPiece.GetComponent<ArrangingPuzzlePiece> ();
    
            puzzlePiece.Initialise (arrangingPuzzleManager, null, null);
            KickStarter.runtimeInventory.SetNull ();
    
            puzzlePiece.Select ();
        }
    
        private Vector3 GetMouseWorldPosition ()
        {
            Vector3 mousePosition = KickStarter.playerInput.GetMousePosition ();
            mousePosition.z = Mathf.Abs(Camera.main.transform.position.z);
            return Camera.main.ScreenToWorldPoint(mousePosition);
        }
    
    }
    
  • edited March 5

    Thanks Chris!

    The script does solve the issue with spawning behind the menu bar - it seems to be the mouse has to just exit the menu frame and then it spawns - halft outside the bar and half behind.
    https://imgur.com/a/7VsWMxo

    If moved behind the menu bar and mouse release it will be behind the bar.
    Can the menu be set to be a "Collider", so I can't go behind it at all?

  • Sorry, can you rephrase that? I'm not clear on your meaning.

  • edited March 6

    Sorry for the confusion.
    After dragging the item into the scene and not releasing it with a click, It is still possible to drag back over the inventory bar, where it will be placed behind the bar and therefore not reachable.
    So my idea was if it was if it was possible to have the menu bar being a blocker so it its only possible to drag the item around in the scene and not back over menu again (And then the issue with the items being placed behind the menu bar will also not be an issue)

    Hope it makes sense

    Thanks again.

  • edited March 6

    Thanks for the help, I solved it.
    I was just experiementet a little with ChatGPT, and to my big surprise it knows AC very well and can provide detailed guidance.
    Thanks a bunch Chris - it never ceases to amaze me the help and support you give beside the regular updates that makes AC one of a kind.
    Much much appreciated.

  • Hi there, so sorry for my delayed response - Chris was right, I am working on something similar.

    If there is still something you need help with from me please let me know!

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.