I want my game to use different things players can collect, like ammunition. Is it possible to display variables to the player using states?
Thanks.
I want my game to use different things players can collect, like ammunition. Is it possible to display variables to the player using states?
Thanks.
Hi,
Absolutely you could, what you are talking about really is adding an inventory system. This kind of functionality can get quite complicated quite quickly, but there’s no reason why you can’t approach it in sensible, smaller steps.
I’d suggest starting by breaking down the functionality you want, for example, you have mentioned about a player being able to collect things and given an example of ammunition. Instantly from that I think of the following questions;
If you start by asking yourself questions like these and really fleshing out your ideas it will save you a lot of headaches when it comes to actually designing the system you want to put in place, and this, why it may sound like work, will take less time than trying to untangle the potential mess the code can get in if not thought out initially.
Next I’d consider approaching the implementation in stages, so if you wanted something like this;
The first stage may be to modify your states to enable them store the additional data, e.g. the items you want to have at each location at the beginning.
From here, you could update your code fairly easily to just display the item(s) that are at that location. I’m going to assume that you would want more than one item to be at any one location, so a List might be a useful way to go, and then you could just iterate through the list to display the Item(s) to the screen.
At this stage there’s no interaction to collect/drop items, but you have enable them to be configured from the beginning of your game and can see them at each location as you progress through your story.
Perhaps the next stage is to enable the player to take the items, using the List approach again, you would need to remove the item from the list for the specific state, but you need somewhere to put it as well, so you’d need to perhaps consider having a Player object which also has a List which you might call Inventory for example. The action of taking would remove the item from the list in the state and add it to the list in the player’s inventory.
At this stage I probably wouldn’t worry about showing the player’s inventory, just focus on the item being taken from the room/location. When you come back to that state the code that displays the items that are available should now not be showing the taken object. This gives you an opportunity to check that the story text still makes sense too.
Next I’d go with the drop functionality. Its going to be the reverse of what you’ve written for taking items really isn’t it, so this time removing the item from the player’s inventory list and adding it to the list for the current state. Testing this should now reveal an item in the room/location that wasn’t there when the game started. You could also do some edge case tests here, like collecting all of the items from all of the rooms/locations and then dropping them all into one room/location (state), how does it look on the screen? This is the kind of stuff a player may do, so if half of the items disappear off the bottom of the screen you have some UI considerations to take on board also.
Perhaps the next stage is giving the player the ability to see their inventory, is this going to be something which is on screen all the time, or is this perhaps something that the player can activate by entering “inventory” at any stage during the game and see a list of their items?
Consider what additional functionality may be required when viewing the inventory. If your approach is graphical for example, you’d probably want to add an option to drop the item. If you are just going to output a list of items in text then your existing drop functionality is already in place.
I would recommend going with the most simple approach first in all cases and gradually building up from there.
At some point you will want to add use item functionality. Things could get quite complicated here depending how to approach it. For example, will items that are used enable other options to be presented to the player, or will it be for the player to think about the items they have and then try to use them. Consider if you will a state with a lock door. Does another option appear that says “Use the gold key” if they have a gold key in their inventory, or, does the player have to type “use gold key” for example.
It is important to consider these interactions because they will be much different to the numeric based interactions you have already built into this game.
The greater the granularity the greater the complexity. If I can collect an “apple”, I might expect to be able to “eat apple” rather than “use apple”, so now we would need some form of “eating” mechanic. We’d need to consider perhaps the player’s health, maybe the apple restores 5hp, if so, the apple item needs to hold data that indicates how many hp it will restore - and so on.
Returning to your original example of ammunition, again, start simple would be my suggestion. The player collects a gun. The player collects ammunition. The player uses the gun - assume at that point they use all of the ammunition, remove it from their inventory, now they have a gun but with no ammo, rather than - at least initially - worrying about how many shots were fired.
I hope the above is of use and I look forward to seeing your implementation of an inventory system in your game - do keep us posted!
Wow, thank you for the detailed response! You’ve really given me insight on how to plan out the game design instead of just jumping right into the code.
I was looking at this Unity doc, and from what I understand a List is similar to an Array, except you can add and remove things from a list instead of having a fixed array.
It seems that objects in Lists can have their own variables stored in them… So would a viable way of creating items in different places be to have a State var for each item in the List, where I can declare which state they will appear in? Then when the player picks up an item, remove it from that List and add it to the players inventory List like you suggested.
eg: item.Add( new Item("Assault Rifle", "A1b Cargo Hold"));
(This probably isn’t the correct way to code this, just using the Unity Doc as a reference)
And now when you are talking about more complex items such as the apple, or let’s say different items with different uses - would they each get their own script or just have a long string of variables for the list that I can apply to these items?
for example,
item.Add( new Item("Assault Rifle", "A1b Cargo Hold", 30, 0, 0));
item.Add( new Item("Golden Apple", "B2 Dumpster", 0, 50, 0));
Where the variables would be Name, State, Ammunition, Health Restored, etc. This seems like it would clutter quickly though. I may be thinking in too much detail for the stage I’m currently at.
Again, thanks for your help here does anyone know if/when Lists are going to be covered in the Unity2D course?
Hi,
Wow, thank you for the detailed response!
You’re very welcome
So would a viable way of creating items in different places be to have a State var for each item in the List, where I can declare which state they will appear in?
If I understand you correctly, that sounds like you are considering have one list containing all of the items, and then each item would store where it was in the game, e.g. which room/location. The downside of this approach would be that every time you have a play enter a new room/location, you would have to iterate through the list of all items, and check each item to see whether it was in that room/location or not. That’s a lot of iterating.
What I meant was the other way around.
So for example, this is a copy of the State.cs code from GameDev.tv’s GitHub repository;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(menuName = "State")]
public class State : ScriptableObject
{
[TextArea(10,14)] [SerializeField] string storyText;
[SerializeField] State[] nextStates;
public string GetStateStory()
{
return storyText;
}
public State[] GetNextStates()
{
return nextStates;
}
}
At the moment there is a variable for the story text, and an array of other states which will be used for the options. What I was suggesting would add a List to this class, as a member variable, as such, every state would then have a list which could contain items.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(menuName = "State")]
public class State : ScriptableObject
{
[TextArea(10,14)] [SerializeField] string storyText;
[SerializeField] State[] nextStates;
[SerializeField] List<Item> items;
public string GetStateStory()
{
return storyText;
}
public State[] GetNextStates()
{
return nextStates;
}
}
In the above I have added List<Item> items;
to declare a member variable, note the type, Item
, this is another class you would need to define, and initially want to keep fairly simple, for example;
using UnityEngine;
[CreateAssetMenu(menuName = "Item")]
public class Item : ScriptableObject
{
[SerializeField]
private string name;
// ...
}
Note, you could choose to not use scriptable objects as the approach, but as you’ve already experienced their use for the states, you could continue to use them for your objects, which will then give you the ability to create your objects as assets - quite nice.
In the above, there’s a class definition and it just has contains one field, name
, e.g. the name of the item.
With regards to the player’s inventory, I don’t think the original Text 101 game has the concept of a player from memory, there is the AdventureGame.cs, this is effectively managing the game as it progresses, it updates the states and player input. You could add a player inventory here, personally I’d probably break it out separately, but again, in the interests of starting small this may be a place to consider adding a List which can be used to hold Items, representing the player’s inventory, for example;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class AdventureGame : MonoBehaviour
{
[SerializeField] Text textComponent;
[SerializeField] State startingState;
List<Item> inventory;
State state;
// ....
}
Note, you need to instantiate Lists, in the case of the State.cs example I gave, this will be managed via the Inspector. In the example above, it’s a private list and hasn’t been instantiated at this time, nor is it exposed via the Inspector.
With regards to your second question about the items…
Start small. In the above example you have a new class called Item
and the item just has a name, no other data. This would be sufficient for your to get through the first stage of my initial suggestion, e.g. use the original Text 101 model, expand on the state class to hold items, and then add some items.
All that is needed then is to output the items to the screen, you could do this via the existing Start
method in AdventureGame.cs to get things started;
void Start()
{
state = startingState;
textComponent.text = state.GetStateStory();
textComponent.text += "\n";
textComponent.text += "You can also see; " + state.GetItems();
}
You would, of course, need that GetItems
method in State.cs
, it might look like this;
public string GetItems()
{
string concatenatedItems = string.Empty;
if(items != null)
{
foreach(Item item in items)
{
concatenatedItems += item.name + ", ";
}
}
return concatenatedItems;
}
All the above is going to do is iterate through all of the items in the List within the specific State and add their names to a string. I will also leave a trailing comma, but this is just a quick example, you can tidy it up
With the above working, you could then consider expanding on the Item class, as needed. Perhaps you add a Description field, in your game you could then enable a “Examine” mechanic, if a player examines a specific object, the description of that item is then displayed. You could add a Weight field, perhaps your player can only carry so much weight, this would allow you to limit the number of items the player can carry, and so on.
Just to reiterate - start small. See if you can expand on the State class so that a state can contain one or more items. Create a few items, add them to your states and see if you can get the output on the screen to update to show what items are at that room/location as you progress through the story. This would be a most excellent start.
Hope the above helps
Hope the above helps
Very much so! I’ll post again soon when I have something to show
Great, I will look forward to hearing how you get on and hopefully play a WebGL build of your game and see some items!
@Rob or anyone digging through this subject:
Would this inventory list of objects be a similarly recommended way to “store choices”?
I’m looking to implement a mechanic where the game remembers that in an earlier state the player chose eg: “2 - Be nice to this person”, which would trigger a new story branch (or different options) later in the game.
Should I create a GameObject which represents that choice and give it to the player if they choose it, same as a “key” moved into the inventory?
Secondly, since we’re using a press-1-2-3 mechanic (or I’ve managed to make buttons to click) how would I assign an object to a choice option and move it to player list, since my game mechanics don’t allow player to type “pick up rock” etc.
I’ve been sifting through a lot of posts so I appreciate any advice you guys have.
To your first point; I don’t see any need to to link a GameObject to choices that the player makes. I think it would be easier to store choices in a ScriptableObject (which I am in love with now!!). Any script that needs to know what choices the player has made can just reference the scriptableobject.
Secondly, since we’re using a press-1-2-3 mechanic …
I think that you could also use ScriptableObjects here as well. I would make a new one called PlayerInventory. From there, you can create assets from that ScriptableObject (using [CreateAssetMenu]). This way, it’s easy to keep one ScriptableObject asset for their current inventory, a tutorial inventory if need be, etc.
I’m not sure if this is the best way to go about your second point, but it’s what I might do.
Some resources that may be helpful to you:
What to know about scriptableobjects and how to implement basic variables that any class can access to make your game modular and easy to build upon
A lecture I watched that really goes into detail about how scriptableobjects work and why they can be really useful.
I hope I was able to help. I’d be glad to answer more of your questions if you have any, I’ve been using scriptableobjects in my first game outside of the course. Good luck!
This is such an awesome, short, general guide into game design and how to go about thinking of how to break down and implement features you might wanna add into your game!
It is fantastic and I’m glad I came across this now, while I’m still at the beginning of my game development journey. Thanks for having taken the time to write such a detailed response to the original poster’s question. This whole discussion is helpful in so many ways! c:
Hi @Potayto, I’ve not been here for sometime, but I received an email notifcation with your kind words and just wanted to say that I appreciate your reply.
All the best with your game dev journey