- Home /
Looting a Chest with multiple gameobjects
Hello All,
This is probably something simple or I may be staring at the screen to long but I cant quite seem to figure it out.
In the most basic terms I have my player game object and a chest gameobject to the player to loot. The chest is a prefab with an array of gameobjects, mana pot, health pot, etc that they player could loot. Its declared as a public array with a script on the chest gameobject:
public GameObject[] chestContents;
And I can go through and drag/drop items, etc and do a loop to make sure the contents are correct:
for (int i = 0; i < chestContents.Length; i++)
{
Debug.Log("Item number is " + i + " is named " + chestContents[i].name);
}
What I am trying to do is when the player enters the chest collider and Hits E to loot, to Debug.Log the contents.
Right now the issue I am having is accessing the public array from my chest gameobject from my player gameobject script. I am trying to get the array Length, names, etc. No matter what I try the length is always 1 and the item names dont populate. I feel I am not accessing it publicly correct somehow. What am I missing?
here is some of my code on my player script, he kneels down to open the chest and animates the chest open, which is all working OK.
public GameObject[] swordChestList;
public int swordListLength;
void OnTriggerStay(Collider col)
{
if (col.gameObject.tag == "sword_chest" && Input.GetKeyDown(KeyCode.E))
{
myAnimator.SetTrigger("kneel_down");
col.gameObject.GetComponent<Animation>().Play();
Debug.Log("Opening Chest");
swordChestList = GameObject.FindGameObjectsWithTag("sword_chest");
swordListLength = swordChestList.Length;
Debug.Log(swordListLength);
}
}
Any help would be much appreciated. I have access other gameobjects before and chidren of objects with scripting before, so I am missing something.
If there is a better way to do this I am welcome to changes. I have tried Lists, but had almost the same results. Thanks!
I'm not sure of what you try to do with GameObject.FindGameObjectsWithTag("sword_chest").
What this function returns is an array with ALL the active GameObjects with tag = "sword_chest". So if you only have one item in your Hierarchy with this tag the length will always be one.
What you may be trying to do is this:
GameObject[] allSwordChests = GameObject.FindGameObjectsWithTag("sword_chest"); // Get all the game object with tag = "sword_chest"
GameObject myChest = allSwordChests[0]; // Get the first chest found.
GameObject myChestContent = myChest.GetComponent().chestContents; // Get the script on the chest that has the list of the content and get this list from it.
Debug.Log(myChestContent.Length);
Thank you for the reply. That helped my thought process out a lot!
I think my brain fart was not creating a new GameObject array to get the contents, like you said, i was just getting the number of chests.
I was able to get it working with your help and the following code:
chestArray is the name of the chest script, and chestContents is the gameobject array.
GameObject[] myChestContents = swordChestList.GetComponent<chestArray>().chestContents;
Debug.Log(myChestContents.Length);
for (int i = 0; i < myChestContents.Length; i++)
{
Debug.Log("Item number is " + i + " is named " + myChestContents[i].name);
}
I was also able to get it working with Send$$anonymous$$essage, but I think that is the "incorrect" way to do it? Thanks for the help!
Answer by jmgek · Jan 13, 2017 at 04:56 PM
While @quentionLG had a very good answer and it seems its the solution I would like to explain something that I see that could help you out very much and in my opinion on of the strongest uses of OOP, you're going about the problem a little wrong since you're going to have to first generate your game object that you will put in your chest, (specifically because its a game object type, you don't have access to gameobject.itemType = sword, etc.) plus other problems that I won't bore you with here.
What you want to do is create a class of items:
public class Item{
public string name; //sword, staff, etc
public float damage;
public int weight;
public float sellPrice;
....
//Create a constructor to handle the creation.
}
public class Chest{
List<Item> listOfItems = new List<Item>();
//An array would also work but with an array you need to initialize it's size, Lists are re sizable.
int spaceInChest = 10;
public void AddToChest(Item item)
{
if(spaceInChest <10)
listOfItems.add(item);
...
}
public void RemoveFromChest()...
public void UnlockChest()...
}
//Create a item and a chest then add the item to the chest with the above classes.
Item someItem = new Item();
Chest someChest = new Chest();
someChest.AddToChest(someItem);
Does this make sense? This is the most important (In my opinion) thing in OOP, this saves you time and allows you to create a class exactly how you need to instead of doing all this backwards work trying to add properties to a gameObject.
Thats great information jmgek, and is probably what I need to be doing. Currently what I am doing seems like "work harder, not smarter". I think i need to do some tutorials on classes, but that seems what I should be doing. $$anonymous$$y question would be, would you put this script on any object, or more of a "master" script? Thanks again!
Yes, if you are still unaware of classes and how to use them as containers for your data please take an hour to learn about them: https://www.youtube.com/watch?v=oYb$$anonymous$$$$anonymous$$T_YEhc
Think of a class as a container for properties (Variables) and methods (things to access and preform logic) You want to create a class of type Items to hold all the properties like damage, price, speed, color, prefab, etc. Everything that you want an item to have.
Then you want to add the methods to that class to do things like:
Damage other player (Swing())
Recharge item with magic (Recharge())
Add to inventory (Add())
Remove from inventory (Remove())
So you can call something like: sword.Swing(someEnemy);
See how easy that is? You create the method once and it handles the objects for you.
With the current way you are doing things I would say you have to do 3 to 4 times more work, and it's not extendable.
Going with your way a few things your making hard for yourself: 1. You have to generate a gameobject with each item (hard coded) with all its values, dmg, price, etc. 2. How are you going to handle multiple chests with your system? You would have to make a chest manager to handle them 3. your going to have a hard time accessing data from your item, how are you going to create a proper system for using a sword, staff, spear, etc. 4. How are you going to handle your items? How are you going to say 'this is' a sword? By name? 5. What happens if you want to change the damage or update the damage on a sword? How can you do that easily with a game object?
Take some time to watch that video, trust me it's going to help you more than you realize. Let me know if you have further questions.
Awesome, both of you have been very helpful. Is there a way to mark you both as answers? ( Sorry, i am a bit new to the forum.) Thanks!
@millej23 Hey man, that's awesome! So glad you're picking it up well. It looks like you understand constructors as well. This to me is the most important part of OOP.
I am sure you understand this but I am a little curious as to why you have 'sitem1, sitem2' as opposed to having a list to contain your items? I can see if if you want to hold 2 items, but I may be over looking something:
public class Chest
{
public int chestID;
public string chestName;
public List<Item> listOfItems = new List<Item>();
//Constructor code
public void AddToChest(Item item)
{
listOfItems.add(item);
}
}
Also look into having your chest inherit from a base class of type 'Inventory' so you can use it on a character class or a backpack or even a hole in the ground https://www.youtube.com/watch?v=OJfddgrWvAk:
pubic class Inventory
{
public int capacity;
public string name;
public GameObject prefab;
public List<Item> listOfItems = new List<Item>();
//Virtual methods if you want them.
}
public class Chest : Inventory
{
//This now contains all the properties of Inventory eg capacity, name, prefab.
//Override methods if you want to
}
Great job man keep it up!
@jmgek Was actually working on that now. I have an ItemsList and have 4 itmes in there now. $$anonymous$$ade a new constructor to take the aruguments and it was added! I need to do a lot of cleanup and testing but I think its clicking a bit more. Thank you!
:D