Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Gochida · Feb 18, 2015 at 10:01 AM · c#itemcommunicationevent-handlinguse

How do I 'use an item'?

So, I have a very nice inventory GUi set up, and I can take GameObjects with an item script attached to them, and pick them up and put them in the inventory. When I right click an item, what should happen is the item is 'used'. I've got it recording these clicks... but I have no idea how to make the item 'go'.

I believe I need two types of items. A instant use item (potions say) and delayed use items (like a grenade, that brings up a targeting cursor and isn't actually used until thrown)

Unfortunately, I'm banging my head against the keyboard trying to figure out a clean way to do this without a bunch of delegate calls just to use one item, and might end up mis-triggering if the player is mashing the mouse.

How can I trigger the effects of an item. And if the item is used successfully, consume/destroy the item? Is there some way to just call a 'UseItem' function and pass it some details on what to do?

This is InventoryController which manages incoming items and outgoing items. It subscribes to a event 'slotClickedEvent' which is triggered by IPointerDown on a Slot (which is just a button)

 using UnityEngine;
 using System.Collections;
 using System;
 using UnityEngine.UI;
 
 //Player checks inventory to see what they are carrying
 
 //regarding passing of "Items" around.
 //We HOLD and PASS GameObjects
 //We ACCESS the Item component to do Item-y things.
 
 public class InventoryController : MonoBehaviour
 {
     //...bunch of graphical related vars here...
     private GameObject objectInHand //used with some accessors to track if mouse is holding an item. Mostly related to click/drag moving items between slots
     private ArrayList allSlots;
     private int emptySlots;

     void Start()
     {
         //...
         EventManager.slotClickedEvent += SlotClicked;
     }

     //code for picking up and adding is item here
 
     private void SlotClicked(Slot slot)
     {
         if (Input.GetMouseButtonDown(0))
         {   
             //logic for picking up and placing items here
         }
         else if (Input.GetMouseButtonDown(1) && slot.hasUseableItem)
         {
             ////////////////////////////////
             //use item code would go here//
 
         }
     }
     //...code for tracking empty slots, adding items from the world etc here...
 }

This is Slot, which is attached to a GUI prefab (has an image attached to another image)

     //public delegate void SlotClickEventDelegate(Slot slot);
     //public static event SlotClickEventDelegate SlotClickEvent;

     private GameObject objectInSlot = null;
     private Item itemInSlot = null;
     public Item item
     { get { return itemInSlot; } }

     // Use this for initialization
     void Start () 
     { //...        
     }

     //...methods for adding/merging/swapping items here...

     public GameObject RemoveItem()
     {
         GameObject obj = objectInSlot;
         objectInSlot = null;
         SetSprite(null, 0.0f);
         itemInSlot = null;
         UpdateStackText(0);
         return obj;       
     }

     public void OnPointerDown (PointerEventData data) 
     {
         EventManager.SendSlotClickEvent(this);
     }
 }

This is Item, which is attached to a GameObject meant to be used as.. an Item.

 public class Item : MonoBehaviour {
 
     public ItemType type;
     public Sprite icon;
     //public string name;
     
     public void Use()
     {
         
 
     }
 }
Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Nymisu · Feb 18, 2015 at 12:32 PM 0
Share

Impossible to answer without actually knowing what your code is. There's no one way to do an inventory system. Do you use a library? Perhaps an array? Or a list? Do you use buttons to display the items?

Even if we wish to be, we're not psychic.

avatar image Gochida · Feb 18, 2015 at 09:33 PM 0
Share

Ok, I pasted in parts of the script I'm using (there's a lot of ad$$anonymous$$istrative stuff that would pad this out to several screens if left in. Those just handles click/drag/drop of icons in the inventory mostly.) I think this is enough to get the gist of things behind clicking and using an item.

It starts with clicking a Slot prefab, which sends itself via event to InventoryController, which then makes a decision based on what key was pressed. In this case, $$anonymous$$ouse 1 for use whats in the Slot passed. Slot allows access to the item.

1 Reply

· Add your reply
  • Sort: 
avatar image
1

Answer by Zarenityx · Feb 18, 2015 at 09:54 PM

Personally, this is not how I would go about making an inventory system. From what I could understand your items are actually GameObjects, and each Item's specific behavior is controlled by the value of an enum. The problem here is that accessing the item component can be slow, and all of the item's functions and attributes have to be in the item component, which can be tedious to make and doesn't easily allow for the creation of different types of items.

What I would do is essentially separate the Item from the Object. In my inventory systems, I make a class (one that does NOT inherit from MonoBehavior) called Item, where I store the basic item data, such as the name, amount, ID, GUI image/mesh, etc, and a few virtual functions, such as Use(), Equip(), Unequip(), etc.

Once you have the basic Item class, then you can start making your actual items by making other classes that inherit from Item, and override the functions and variables. This is where #region directives really come in handy.

Then make a 'real' script (a monobehavior one), to manage the inventory and call the appropriate functions when something happens, such as calling Use() when clicked.

Finally, you want a way to make the items and the objects work together, so a very simple script can be made such that when the object is interacted with, it looks up the actual Item you are talking about (I would create a static class with a list of all possible items), gives you that item/ increases it's quantity, and then gets rid of the actual object.

As for grenades vs potions, that change is easily implemented by changing whether or not you Equip() or Use() the item when you call your "clicked" function.

It might seem like extra work to start out with, but do you really want to be stuck with a bunch of ifs or switch-cases, and then extra work to save the inventory to a file when you end up with hundreds of items? Plus, you could easily take these scripts, make them into a UnityPackage, and use them in other projects with only a few modifications, and if you can already make an array of items display as a GUI, organized in stacks, the conversion of the GUI system should be trivial.

I hope this helps! I understand that scrapping most of a framework can be hard, but it is definitely worth it to have an optimized and polymorphic system for things like this- believe me, I have tried and failed at least 5 or so ways to make a voxel engine, and the one I have now is at a point where I may need to start over again, but that's just part of the learning process, I guess.

Comment
Add comment · Show 8 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Gochida · Feb 18, 2015 at 10:10 PM 0
Share

That sounds like a solid plan.

When I want to do the effects of a Use, say, heal the player - should I be doing some sort of look up (like GameObject.FindWithTag<>()? Is there a better way to grab disparate objects to call functions on them?)

avatar image Nymisu · Feb 19, 2015 at 08:46 AM 0
Share

You can create a script for instancing references to gameobjects. It's as simple as making a gameobject list if you wish to go this way.

Also, if you're going to use delegates, i warmly recommend learning the lambda expression (=>), it's much faster than a delegate, and requires less code.

avatar image Gochida · Feb 19, 2015 at 10:00 PM 0
Share

Not sure I understand how I would use lambda to simplify making an event.

Presently, to make an event that other objects can subscribe to, I do this

     public delegate void PickupItemDelegate(GameObject itemObj);
     public static event PickupItemDelegate pickupItemEvent;
     public static void SendPickupItemEvent(GameObject itemObj)
     {
         pickupItemEvent(itemObj);
     }

which I got from Unity's tutorial on events. I stick a bunch of these into a class I call Event$$anonymous$$anager and just have one object subscribe a function to an event, and another object call the corresponding 'SendXXXXX'

Is there some way Lambda can be used to simplify this big block of code? Googling "c# lambda events" turned up a way to subscribe to these events with a lambda function, but nothing on simplifying the above.

avatar image DanSuperGP · Feb 19, 2015 at 10:17 PM 0
Share

Just a little tip...

if you change the event line to

 public static event PickupItemDelegate pickupItemEvent = delegate {};

You don't have to worry about checking if pickupItemEvent is null, or throwing an exception if nothing is subscribed to it.

Also... I wouldn't subscribe anonymous functions (declared with lambdas) to this kind of event because the lack of a name make removing them impossible, which is totally non-optimal.

Lamdas are better for when you have a method that takes a delegate as a parameter.... like for an oncomplete

 public delegate void OnCompleteDelegate ();
 
 public void actThenCallOnComplete( string someWords, OnCompleteDelegate callOnComplete)
 {
      Debug.Log(someWords);
      callOnComplete();
 
 }
 
 void Start()
 {
     actThenCallOnComplete(  "some text" , () => {  Debug.Log(" some more text."); } );
 }
avatar image Gochida · Feb 20, 2015 at 05:58 AM 0
Share

Good to know, thanks for the tip!

Show more comments

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

4 People are following this question.

avatar image avatar image avatar image avatar image

Related Questions

Multiple Cars not working 1 Answer

Distribute terrain in zones 3 Answers

Invoking Effects of (Random) Items (C#) 0 Answers

Decorator pattern for inventory item class 0 Answers

Referencing game objects/script communication 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges