- Home /
How to Pick up 1 collider Object at a time, Vs. all at once?
My issue here is I have multiple items with the same range or sphere and cylinder colliders. Now they work perfectly fine, but my dilema is when I pick up an object, and a different object that I wasnt even meaning to pick up. (because im in the same collider radius), it picks up all said items at the same time lol. Now how would one go about picking up one item at a time? And on top of that, that the item im actually looking at has more of a priority over the others that are further away?
I would assume I put maybe a boolean somewhere? Maybe even a coroutine? Just not sure where I should place this. Was hoping some of you guys could lend some insight as to how you would possibly approach this? Thanks guys!
CODE:
public class PistolColtAmmo : MonoBehaviour
{
// public int bagAmmo;
private static int bagAmmo;
private static bool hasBag;
public int ammoAmt;
[SerializeField] public int fullClip;
[SerializeField]
private Inventory inventory;
// [SerializeField]
// private Player player;
private static List<Item> itemList;
// public static List<Item> itemList = new List<Item>();
[SerializeField] AudioSource ammoPickup;
public void OnTriggerStay(Collider other)
{
// check if its the player:
if(other.tag == "Player")
{
// Grab global bag variable:
bagAmmo = GunScript.bagAmmo;
hasBag = PlayerBehavior.hasBag;
itemList = PlayerBehavior.itemList;
// Check to see if user hits the "E" key:
if(Input.GetKeyDown(KeyCode.E))
{
// Creating a random amount of ammo amount between 8 and 15 to put inside the clip.
// Otherwise override with full clip size:
// var ammoAmt = Random.Range(8,15);
var ammoAmt = fullClip; // Or Randomized ammount:
var newAmt = bagAmmo + ammoAmt;
HandgunScriptLPFP.bagAmmo = newAmt;
/// END AMMO BAG:---------------
// Play ammo pickup sound:
ammoPickup.Play();
//Destroy Ammo after picked up Object:
Destroy(this.gameObject);
}
}
}
}
Answer by Hellium · Sep 13, 2020 at 10:03 AM
The pickup script should definitely be on the Player instead of the ammo itself.
I also advise having a base class for all your ammo called PickableAmmo
, you will understand why:
public abstract class PickableAmmo : MonoBehaviour
{
[SerializeField]
private int amount;
public int Amount { get { return amount; } }
protected abstract void RefillPlayerAmmo(Inventory inventory);
}
public class AmmoPickup : MonoBehaviour
{
private List<PickableAmmo> ammoInRange = new List<PickableAmmo>();
[SerializeField]
private AudioSource ammoPickupAudioSource;
[SerializeField]
private Inventory inventory;
private void Update()
{
if(Input.GetKeyDown(KeyCode.E) && ammoInRange.Count > 0)
{
PickableAmmo ammo = FindPickableAmmoClosestToView();
if(ammo != null)
PickAmmo(ammo);
}
}
private PickableAmmo FindPickableAmmoClosestToView()
{
PickableAmmo ammoToPick = null;
float bestDotProduct = -1;
foreach(PickableAmmo ammo in ammoInRange)
{
// https://docs.unity3d.com/462/Documentation/Manual/UnderstandingVectorArithmetic.html
// Check whether the player is almost looking at the ammo
float dot = Vector3.Dot(transform.forward, ammo.transform.position - transform.position);
if(dot < bestDotProduct && dot > 0.866f)
{
ammoToPick = ammo;
bestDotProduct = dot;
}
}
return ammoToPick;
}
private void PickAmmo(PickableAmmo ammo)
{
ammo.RefillPlayerAmmo(inventory);
ammoPickupAudioSource.Play();
Destroy(ammo.gameObject);
}
private void OnTriggerEnter(Collider other)
{
PickableAmmo pickableAmmo = other.GetComponent<PickableAmmo>();
if(pickableAmmo != null)
{
ammoInRange.Add(pickableAmmo);
}
}
private void OnTriggerExit(Collider other)
{
PickableAmmo pickableAmmo = other.GetComponent<PickableAmmo>();
if(pickableAmmo != null)
{
ammoInRange.Remove(pickableAmmo);
}
}
}
Then the subclasses of PickableAmmo will just implement the RefillPlayerAmmo function
public class PistolColtAmmo : PickableAmmo
{
protected override void RefillPlayerAmmo(Inventory inventory)
{
// Having static functions to manage data is a very bad idea IMO
HandgunScriptLPFP.bagAmmo += Amount;
}
}
Freaking amazing dude... LITERALLY BLEW $$anonymous$$ Y $$anonymous$$IND! THank you so much.. I will try to implement this right away.
Also, I posted what I thought was a reply to your code here, I was asking if you could take a look at another script of $$anonymous$$e, that was derived form this. But it said something about awaiting approval lol. SO ya, if you get a chance, please take a look, regardless, THANKS AGAIN $$anonymous$$AN!!
I didn't find your the question you are referring to. Is it C# List Of Dictionaries?
No Im refering to this post here, I Posted a response last night off my phone, and it said "Waiting to be approved by a moderator" However Im now seeing it anywhere? Not sure what happened... But I cant fit it all under this reply, so I will post it under an answer. Thanks again man, I really appreciate it. Been stuck on this for a while.
Answer by EsC369 · Sep 16, 2020 at 08:49 PM
WOW! You seriously blew my mind... You showed me things I havent seen before! And Duh... Of course I should have it on the player rather than the item object itself... Seems so obvious to me now that you point it out.. I really appreciate you taking the time to write out what is to me a pretty elaborate updated version of my script. Before I ask a few more questions. I was curious if you could take a look at my item script? It was actually derived from the script I posted above as I originally was writing the script for ammo. But as I started to put it on other items, I tried to make it a bit more universal. I hate to ask this after the response you just gave me, but I just cant seem to get this right no matter what I do... Could you possibly show me what im doing wrong here? I will for sure try to apply your upgraded code above to my new version of "ItemScript". But please let me know if you have any more insight on this.
Currently the bag is attached to the player hard coded at 50000; ( All the more reason to put this script under player which I will do soon enough, hopefulyl will fix some of my issues). Anyways, the issue im having here, it at times when grabbing the items, it works perfectly. Other times especially if I spam "E" (Which is my pick up key) a bunch. Like if I dropped lets say a ammo clip, and then spam E on a bunch of items, sometimes it breaks and continues to pick up and add the items regardless of it surpassing the weight threshold... Other times, the current total weight, says it has double, than what it actually has... Its really weird man... Im not sure what causing it at all... Anyways, I will try to implement what you wrote out for me in a bit. But if you have the time and are willing, please take a peek at this and tell me what the heck im doing wrong here lol.
Code of current item script:
// 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();
}
}
}
}
Also thanks for the advice on everything, as well with the static variables. I usually dont use them, I try to grab the component and change as needed that way, but those statics are more so for testing. I plan on not really using them.
This script works for the most part. But the issue im having now is with the weight... NO matter what I do... I just cant seem to get the weight right... Like it will work the first couple of times, then after a while, it starts to break.
This script was working fine until I tried to add weight... The issue im having here Thanks again!
Your answer
Follow this Question
Related Questions
physics.OverlapSphere colliders 1 Answer
How to check if object are link via other collider 0 Answers
How to Pick up 1 collider Object at a time, Vs. all at once? Item Script 1 Answer
using an objects collider to trigger another objects animation 0 Answers
Spawning an object on the opposite side of an activator object with no overlaps 1 Answer