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 EsC369 · Sep 16, 2020 at 08:00 PM · scripting problemcollidersitem pickup

How to Pick up 1 collider Object at a time, Vs. all at once? Item Script

Having trouble with picking up multiple items at the same time, and as well, weight implementation within my item script. The script worked perfectly fine until I added a weight limitation. Sometimes it works, sometimes it doesnt. Sometimes it allows me to pick up more than the max bag weight threshold, especially if I spam the pick up key. But others, it seesm to work fine? Its very weird..

Code:

  // Variables:
     public int itemAmt;
     public bool dropped = false;
 
     private static int bagAmmo;
     private bool hasBag;
     [SerializeField] public int fullAmt;
     [SerializeField] public bool isItemFull;
     [SerializeField] private Inventory inventory;
     [SerializeField] public int lowRandAmt;
     [SerializeField] public int highRandAmt;
     [SerializeField] AudioSource itemPickupSound;
     [SerializeField] public string itemNameInput;
     [SerializeField] public static int currentTotalWeight;
     public int maxBagWeight;
 
     void Update()
     {
         Debug.Log("hitting update: current weight: "+ currentTotalWeight);
     }
 
     public void OnTriggerStay(Collider other) 
     {
    
         // check if its the player:
         if(other.tag == "Player" && !PlayerBehavior.bagFull)
         {   //Reset CUrrent Total Weight:
             currentTotalWeight = 0;
 
             // Grab global bag variables:
             hasBag = PlayerBehavior.hasBag;
             maxBagWeight = PlayerBehavior.maxBagWeight;
 
             // Check to see if user hits the "E" key:
             if(Input.GetKeyDown(KeyCode.E) && hasBag)
             {
                 // Reset Current Weight And Bag empty bool:
                 if(PlayerBehavior.inv.GetItemList().Count == 0) // If inventory is empty, no point in slowing things down with an uneccessarry for loop.
                 {
                     PlayerBehavior.bagFull = false;
                 }
                 else{
                     foreach(Item item in PlayerBehavior.inv.GetItemList())
                     {
                         if(item.itemType.ToString() == "Money")
                         {
                             currentTotalWeight += item.amount; // Money weight is the same as amt. aka 1 each.
                         }
                         else{
                             currentTotalWeight += item.weight;
                         }
                         
                     }
                     if(currentTotalWeight > 0 && currentTotalWeight < maxBagWeight)
                     {
                         PlayerBehavior.bagFull = false;
                     }
                 }
 
                 // Assign Item Amount Functionality: ---------------------------- 
                 // This is just someting for when IM placing the item, I have checks that make it have these amounts at start up depending. These are Serialized Variables I change from within Unity to determine the values of the item.
                 // Check if the clip is full: If so, then skip randomization:
                 if(!isItemFull && !dropped && itemAmt == 0){
                     // Creating a random amount of ammo amount between low and high to put inside the clip. Otherwise override with full Amount size:
                     itemAmt = Random.Range(lowRandAmt, highRandAmt);
                 }
                 else if(isItemFull && !dropped){ 
                     itemAmt = fullAmt;
 
                     isItemFull = false;
                 }
                 else{
                     itemAmt = itemAmt;
                 }
 
                 Debug.Log("Current Total Weight Under Item Script: "+ currentTotalWeight);
                 Debug.Log("Current Total max bag weight Under Item Script: "+ maxBagWeight);
                 if(currentTotalWeight < maxBagWeight) 
                 {
                     int leftOver = maxBagWeight - currentTotalWeight;
                     int newWeight;
                     int newAmt;
                     // If Glock Handgun:
                     if(itemNameInput == "Glock_Handgun"){    // NOTE HAND GUN IS HAVING HAVING ISSUES WITH FLOATING SO TURN ON GRAVITY IF ITS A HANDGUN!
                         newWeight = currentTotalWeight + 5000;
 
                         if((newWeight > 0 && newWeight < maxBagWeight)){
                             // Debug.Log("hitting under add pistol glock les than bag weight");
                             PlayerBehavior.inv.AddItem(new Item {
                                 itemType = Item.ItemType.Glock_Handgun, amount = itemAmt, weight = 5000
                             });
                             // Play pickup sound:
                             itemPickupSound.Play();
                             Destroy(this.gameObject);
                         }else{
                             Debug.Log("Cant fit  pistol");
                         }
                     }
                         
 
                     // If PistolAmmo:
                     if(itemNameInput == "Pistol_Ammo"){
                         newWeight = currentTotalWeight + 500;
                         if((newWeight > 0 && newWeight < maxBagWeight)){
                             PlayerBehavior.inv.AddItem(new Item {
                                 itemType = Item.ItemType.Pistol_Ammo, amount = itemAmt, weight = 500
                             });
                             // Play pickup sound:
                             itemPickupSound.Play();
                             Destroy(this.gameObject);
                         }else{
                             Debug.Log("Cant fit  Ammo");
                         }
                     }
 
                 }
                 else{
                     Debug.Log("Bag is full");
                     // itemPickupSound.Play();
                 }
             }
         }
     }


EDIT: Here is my Inventory and item classes. The inventory is only a class, but the itemList is transfered to my player script called 'Player Behavior".

NOTE* The only thing that isnt attached to the player is pretty much the Item script. Which I plan on changing.


Item script:

 public enum ItemType {
         Glock_Handgun,
         Money,
         Pistol_Ammo,
         Rifle_Ammo,
         Sniper_Ammo,
         Shotgun_Ammo
     }
 
     public ItemType itemType;
     public int amount;
     public int weight;
 
     // Get Sprite Function:
     public Sprite GetSprite() {
         switch (itemType) {
             default:
             case ItemType.Glock_Handgun:      return ItemAssets.Instance.glock_Handgun_Sprite;
             case ItemType.Money:              return ItemAssets.Instance.money_Sprite;
             case ItemType.Pistol_Ammo:        return ItemAssets.Instance.pistol_Ammo_Sprite;
         }
     }
 
     public GameObject GetModel() {
         switch (itemType) {
             default:
             case ItemType.Glock_Handgun:      return ItemModelAssets.Instance.glock_Handgun_Model;
             case ItemType.Money:              return ItemModelAssets.Instance.money_Model;
             case ItemType.Pistol_Ammo:        return ItemModelAssets.Instance.pistol_Ammo_Model;
         }
     }
 
     public bool IsStackable()
     {
         // True =  stackable, False =  unstackable:
         switch(itemType) 
         {
             default:
             case ItemType.Money:
                 return true;
             case ItemType.Glock_Handgun:
             case ItemType.Pistol_Ammo:
                 return false;
         }
     }

Inventory Script:

 public class Inventory {
     public static List<Item> itemList;
     public static Inventory Instance;
 
     void Awake(){
         Instance = this;
     }
 
     public Inventory() {
         itemList = new List<Item>();
     }
 
     public void AddItem(Item item)
     {
         // Check if Stackable:
         if(item.IsStackable())
         {   
             // Check if this item type is inside the inventory:
             bool itemAlreadyInInventory = false;
             foreach (Item inventoryItem in itemList){
                 if(inventoryItem.itemType == item.itemType)
                 {
                     inventoryItem.amount += item.amount;
                     itemAlreadyInInventory = true;
                 }
             }
             if(!itemAlreadyInInventory){
                 itemList.Add(item);
             }
 
         }else{
             itemList.Add(item);
         }
 
         PlayerBehavior.bagEmpty = false; 
     }
     
     public List<Item> GetItemList()
     {
         return itemList;
     }
 
 }
Comment
Add comment · Show 1
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 EsC369 · Sep 16, 2020 at 07:56 PM 0
Share

@Hellium This is the new post.. But this one as well was put under moderation?? The heck???

1 Reply

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by Hellium · Sep 16, 2020 at 08:17 PM

Everything below is based on assumptions and from what I understood of your system, and based on the answer I gave you here. Everything here are suggestions and might not be compatible with your current system, but it can give you some ideas. The code has not been tested, I don't even know if it compiles!!


First of all, to make things clear:

  • There should be one inventory, which is a script attached to the player

  • Objects which can be picked should not even know the existence of the inventory

  • There should be another script responsible for picking the objects, also attached to the player.


Then, I am not convinced the amount should be part of the Item class itself. From my point of view, Item should be a class containing data about the item itself and nothing more. The inventory & the pickable items can manage the amount of items you have and the amount to pick.

Item class

Will give you the possibility to create Scriptable Objects for each of your items

 [CreateAssetMenu()]
 public class Item : ScriptableObject
 {
     [SerializeField] private new string name; // The `new` here is to "override" the name variable in the base class
     [SerializeField] private Sprite sprite; // You will be able to get rid of your ItemAssets & ItemModelAssets classes
     [SerializeField] private GameObject model;
     [SerializeField] private bool isStackable;
     
     public string Name { get { return name; } }
     public Sprite Sprite { get { return sprite; } }
     public GameObject Model { get { return model; } }
     public bool IsStackable { get { return isStackable; } }

     // private variable + public getters to make sure nobody but the editor changes the values
 }

 // You can also create subclasses for your gun for instance if you want to specify the size of the magazine

Inventory class

To be attached on the player GameObject

 public class Inventory : MonoBehaviour, IEnumerable<InventoryItem>
 {
     [SerializeField, Min(1)] private int maxWeight = 5000;
     private List<InventoryItem> inventoryItems = new List<InventoryItem>();
 
     public int Weight { get; private set; }
     public int MaxWeight { get { return maxWeight; } }
     public bool IsEmpty { get { return Weight == 0; } }
 
     public void Add(Item item, int quantity, out int quantityAdded)
     {
         InventoryItem inventoryItem = item.IsStackable
             ? GetInventoryItem(item.itemType)
             : null;

         if(inventoryItem == null) // No items of this type present in the bag, or non stackable, add it
         {
             inventoryItem = new InventoryItem{ Item = item, Amount = 0 };
             inventoryItems.Add(inventoryItem);
         }

         // Limit the quantity if needed

         if(item.IsStackable == false)
             quantity = 1;

         StackItem(inventoryItem, quantity, quantityAdded);

         // I would have done the opposite, the player behavior should check whether its inventory is empty or not
         // See `IsEmpty` getter
         PlayerBehavior.bagEmpty = false;
     }

     private void StackItem(InventoryItem inventoryItem, int quantity, out int quantityAdded)
     {
         for(quantityAdded = 0 ; Weight + inventoryItem.Item.weight < MaxWeight && quantityAdded < quantity ; ++quantityAdded)
         {
             inventoryItem.Amount++;
             Weight += inventoryItem.Item.weight;
         }
     }
 
     public InventoryItem GetInventoryItem(Item.ItemType itemType)
     {
         foreach(var inventoryItem in inventoryItems)
         {
             if(inventoryItem.Item.itemType == itemType)
                 return inventoryItem;
         }
 
         return null;
     }

     // Will allow you to call
     // foreach(InventoryItem inventoryItem in inventory)
     //    // Do something
     public IEnumerator<InventoryItem> GetEnumerator()
     {
         return inventoryItems.GetEnumerator();
     }

     IEnumerator IEnumerable.GetEnumerator()
     {
         return this.GetEnumerator();
     }
 
     private class InventoryItem
     {
         public Item Item;
         public int Amount;
     }
 }

PickableItem class

PickableItem class

 public class PickableItem : MonoBehaviour
 {
     // Fill in the inspector, set minAmount & maxAmount to same value
     // if you want a fixed amount, e.g 1 & 1 to add 1 item in the inventory
     [SerializeField] private int minAmount;
     [SerializeField] private int maxAmount;
     [SerializeField] private Item item; // Drag & drop the item ScriptableObject
 
     public int Amount { get; set; }
 
     private void Awake()
     {
         Amount = Random.Range(minAmount, maxAmount);
     }
 
     public Item GetInventoryItem()
     {
         return item;
     }
 }

ItemPickup class

To be attached on the player

 public class ItemPickup : MonoBehaviour
 {
     private List<PickableItem> itemsInRange = new List<PickableItem>();
 
     [SerializeField]
     private AudioSource itemPickupAudioSource;
     
     [SerializeField]
     private Inventory inventory;
 
     private void Update()
     {
         if(Input.GetKeyDown(KeyCode.E) && itemsInRange.Count > 0)
         {
             PickableItem pickableItem = FindPickableItemClosestToView();
             if(pickableItem != null)
                 AddItemToInventory(pickableItem);
         }
     }
 
     private void AddItemToInventory(PickableItem pickableItem)
     {
         Item item = pickableItem.GetInventoryItem();
         int quantityAdded;
         inventory.Add(item, pickableItem.Amount, out quantityAdded);
 
         if(quantityAdded > 0)
             itemPickupAudioSource.Play();
 
         // The condition is optional
         // It's just if you want to keep the item on the ground if
         // you did not picked the whole pile
         if(quantityAdded == pickableItem.Amount)
             Destroy(item.gameObject);
         else
             pickableItem.Amount -= quantityAdded;
     }
 
     private PickableItem FindPickableItemClosestToView()
     {
         PickableItem itemToPick = null;
         float bestDotProduct = -1;
 
         foreach(PickableItem item in itemsInRange)
         {
             // https://docs.unity3d.com/462/Documentation/Manual/UnderstandingVectorArithmetic.html
             // Check whether the player is almost looking at the item
             float dot = Vector3.Dot(transform.forward, item.transform.position - transform.position);
             if(dot < bestDotProduct && dot > 0.866f)
             {
                 itemToPick = item;
                 bestDotProduct = dot;
             }
         }
 
         return itemToPick;
     }
 
     private void OnTriggerEnter(Collider other) 
     {
         PickableItem pickableItem = other.GetComponent<PickableItem>();
         if(pickableItem != null)
         {
             itemsInRange.Add(pickableItem);
         }
     }
     
     private void OnTriggerExit(Collider other) 
     {
         PickableItem pickableItem = other.GetComponent<PickableItem>();
         if(pickableItem != null)
         {
             itemsInRange.Remove(pickableItem);
         }
     }
 }
Comment
Add comment · Show 5 · 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 EsC369 · Sep 16, 2020 at 10:58 PM 0
Share

Wow.... This is very complex stuff! Thanks man! Regardless of the current response and updates to the posts showing you more of my code, this I think will get me on the proper tack. I think my approach was all wrong.. And I may very well have to scrpa and start it over lol. however, until then, check out the other puzzle pices "$$anonymous$$y item and inventory class" Let me know what you think as that may shine a but more understanding to my approach here. Aside from that, thank you very much! You have helped me more in the past few days than the past week of my self taught development lol!

avatar image Hellium EsC369 · Sep 16, 2020 at 11:06 PM 0
Share

I'm glad it helped you. I've added your Inventory & item script to your original question. I can't update my answer right now but I definitely will in the next 24 hours.


I believe ScriptableObjects will be really useful in your situation. But yes, I fear my suggestions will lead to a complete rework of your system. For the best I hope :D

avatar image EsC369 EsC369 · Sep 17, 2020 at 12:09 AM 0
Share

For sure! I actually originally tried to do scriptable object for the items, but it seemed I wasnt able to achieve my goal.. $$anonymous$$aybe im just a turd and possibly implementing it wrong.


I unfortunately havent be able to see your (more updated) response, but hopefully itll show up tomorrow lol. I eagerly await your current update.

Looking at this as a whole, I am afraid I will need to scrap it all... Seriously worried as that is legit about a week or 2 of my trial and error lol! Sucks to start from scratch... I$$anonymous$$ going to try and reverse engineer a bit more until I scrap it. But nonetheless, thanks again man! This is TRULY insightful!

avatar image Hellium EsC369 · Sep 17, 2020 at 08:10 AM 0
Share

I've updated my answer.

Again, I have not tested it at all, I did not even write this in a proper C# IDE, so some fixes might be needed.

I don't want you to start from scratch but now, you have an idea of how I would have done this, pick the things you want from this answer (pun intended).

Cheers

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

243 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Check bool from multiple instances of the same script 2 Answers

[Oculus SDK] How to add colliders to OVRGrabbable at runtime? 2 Answers

Spawning an object on the opposite side of an activator object with no overlaps 1 Answer

OnCollisionEnter for other gameobjects (C#) 2 Answers

Check bool from multiple instances of the same script 0 Answers


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