#Inventory System Discussion

1 messages · Page 1 of 1 (latest)

dire elbow
#

That is a very good Idea!

#

Also, you said the Player component represents the player. So would I pass it the players GameObject or give the player a script called Player?

weary bobcat
#

The GameObject would not be very useful.

#

You'd need to find the player's Radar component somehow

dire elbow
#

I could create a script called Player, and get references to the radar and all that stuff,

#

so that in the Use() method I can just do cs player.radar.scanMultiplier *= upgradeMultiplier;

weary bobcat
#

Yeah, something like that

#

A Player component will probably have actual methods and stuff in it too

#

but you will also create components that are literally just bags of references

#

especially for prefabs

#

it's a lot nicer than having to dig around with GetComponent

dire elbow
#

By bags of references you mean assigning in inspector?

weary bobcat
#

Right

#

For example, your hotbar can be a bunch of instances of a “Hotbar Slot” prefab

#

It could start out like this

#
public class HotbarSlot : MonoBehaviour {
  public Image itemIconDisplay;
  public TMP_Text itemNameDisplay;
}
#

this would, you could do...

#
hotbar[3].itemIconDisplay.sprite = itemSpec.icon;
hotbar[3].itemNameDisplay.text = itemSpec.itemName;
#

You could then make it nicer by making the references private and adding some methods

#
public class HotbarSlot : MonoBehaviour {
  [SerializeField] Image itemIconDisplay;
  [SerializeField] TMP_Text itemNameDisplay;

  public void Display(ItemSpec itemSpec) {
    itemIconDisplay.sprite = itemSpec.icon;
    itemNameDisplay.text = itemSpec.itemName;
  }
}
#

and thus

#
hotbar[3].Display(itemSpec);
#

I have a prefab for displaying a single input hint icon

weary bobcat
#

and all of the logic had to go wherever it was used

weary bobcat
dire elbow
#

For the UpgradeKindEnum would that be in a script or.. where would that be stored?

#

Inventory System Discussion

weary bobcat
#

(in any script file, that is)

#

The only rule with declaring stuff is that you can only have one ScriptableObject or MonoBehaviour.

#

You can stuff a bunch of other classes, structs, and enums into a script file

dire elbow
#

So should I just put it into the UpgradeItemSpec class?

#

the radar doesnt have an upgrades thing yet.

#

also, would the upgrades on the radar be another enum?

weary bobcat
#

They'd be the same enum!

dire elbow
#

Oh!

weary bobcat
#

also, you might have to do a bit more than just |= to combine the enums

#

the idea with [Flags] is that each enum value is 1, 2, 4, 8, 16, ...

#

creating a bitmask

#

so a value of 3 is a combination of the enums with values 1 and 2

#

This makes sense for upgrades that add new features

#

you either have the flash or you don't

#

If it's something where you progressively upgrade it over time, then an enum doesn't make sense

#

e.g. if you can upgrade the flash further after you first unlock it

#

in that case you'd just have an int variable that tracks the flash level

dire elbow
#

Tbh, I feel like it would be easier to just have an int variable for everything, so even if it only does or doesnt have the flash, I could just say that if (flashEnabled == 0) hasFlash = false; else if (flashEnabled > 0) hasFlash = true;

#

Also, I tried creating the scriptable object for this script, and I got a null reference exception

#

Is this script not supposed to be a ScriptableObject?

#

Oh I see, its because its an abstract class

#

How can I assign the itemName?

#

I can't create an instance of the class at all because its abstract.

weary bobcat
dire elbow
#

How do I use the classes that derive from it? Currently they are sitting in my assets and don't do all that much. Would I need to create a list like you said earlier?

weary bobcat
#

If items don't stack and you don't need custom data for each instance (e.g. a durability value), you can just just List<ItemSpec> as an inventory

dire elbow
weary bobcat
#

you can serialize a List<T> just like you can serialize a T[]

dire elbow
#

So like this in start: items = new List<ItemSpec>(5);?

weary bobcat
#

If you want to be able to put some items in the player's inventory when the game starts, just do this:

#
[SerializeField] List<ItemSpec> items;
#

and then set it to have 5 slots in the inspector

#

(and maybe assign some items)

dire elbow
#

Would I need two of these lists? One for the left hand and another for the right hand, even though the right hand only holds one item.

weary bobcat
#

the right hand wouldn't be a list

#

just an ItemSpec

#

and then you'd have a function that goes like...

public void Swap(int hotbarSlot) {
  items[hotbarSlot], rightHand = rightHand, items[hotbarslot];
}
#

maybe a bit too clever :p

#
public void Swap(int hotbarSlot) {
  ItemSpec temp = rightHand;
  rightHand = items[hotbarSlot];
  items[hotbarSlot] = temp;
}
#

less clever

dire elbow
dire elbow
weary bobcat
#

oh right, the syntax is wrong

#

it needs parentheses around the left half

#

too clever :p

#

and the right too

#
(contents[a], contents[b]) = (contents[b], contents[a]);
#

copied from somewhere in my project

#

It's creating a tuple on the right side and then assigning to a tuple on the left side

dire elbow
weary bobcat
#

you'd store the index (an integer)

dire elbow
#

correct?

dire elbow
#

Also, I just set up controls for switching between slots and swapping hands

weary bobcat
dire elbow
#

This is what I did for input

#

Currently I am getting an Argument Out Of Range Exception when using the swapHands key.

weary bobcat
#

then your list is too small

#

or Swap is wrong

dire elbow
#

Oh I know why, I made the list up to 4 but then changed the name so it reset the settings i had in inspector.

#

It works now

#

Now I just gotta set up the actual items.

#

Would this be an effective method to increase the players speed for a few seconds? cs public IEnumerator IncreasePlayerSpeed(int effectLength, int speedAmount) { movement.speed *= speedAmount; yield return new WaitForSeconds(effectLength); }

weary bobcat
#

this would permanently increase your speed

#

you're getting into an "effects" system, which is another place that can get really complicated depending on your requirements

#

I usually prefer to calculate the value as needed, based on a list of active effects

weary bobcat
#

you could accrue rounding errors with floating point math, though

#

so you wind up with, say, a speed of 0.99996 after several powerup cycles

#

An alternative would be to have a List<Powerup> where Powerup looks like...

public class Powerup {
  public float endTime;
  public float speedMultiplier = 1f;
  public float damageMultiplier = 1f;
}

(with more fields as needed)

#

Once per frame, you would throw out all expired powerups, then compute things with them

#
powerups.RemoveAll(powerup => powerup.endTime <= Time.time);

movement.speed = movement.baseSpeed;

foreach (var powerup in powerups) {
  movement.speed *= powerup.speedMultiplier;
}
#

e.g.

dire elbow
weary bobcat
#

the physical things you'll find in the world?

dire elbow
#

Yeah, like, for a consumable, do I instantiate an object with ConsumableItemSpec?

weary bobcat
#

ConsumableItemSpec is not a component, so it can't be attached to a game object

#

You'll want to create an ItemPickup component (a MonoBehaviour, specifically). It'll hold a reference to an ItemSpec.

#

you can start by just making it a cube or something

dire elbow
weary bobcat
#

It’s on the floor

dire elbow
weary bobcat
#

the Display methods takes one

dire elbow
weary bobcat
#

whoever wants to update the hotbar -- probably something inside the player class

#

like when you pick up a new item, or when you swap items

#

you could totally just call Display on every single hotbar slot ever time you do anything to your inventory

dire elbow
#

If the slot is empty wouldn't the method throw an error because there is no ItemSpec assigned?

weary bobcat
#

It should clear itself if you give it a null reference.

dire elbow
#

But I'm not sure how to assign items to the slots. How do I create the items with the data?

#

Also, all of those errors are null reference exceptions

#

Since there is nothing assigned by default.

weary bobcat
dire elbow
weary bobcat
#

I'm talking about assets: instances of ConsumableItemSpec (or UpgradeItemSpec, or some other kind of item) in your Project folder

#

you need to add CreateAssetMenu to this class so that you can create assets out of it

dire elbow
weary bobcat
#

So that's where things get more complicated

#

If you want the radar gun to be exactly the same sort of "item" as an upgrade or a consumable, you now need to be able to turn an ItemSpec into a thing that can actually do stuff in the world

#

I suppose you could just make a new kind of item whose Use method does whatever radar does

#

But to be able to apply upgrades to the item, you'd need to create a new class to store information about those upgrades

#

remember when I was talking about having an ItemData class?

#

this would be a situation where you need that

dire elbow
#

Do I need to rework the whole inventory system to account for the radar object?

#

I can start reworking inventory things tomorrow

#

its bed time :)

weary bobcat
#

An alternative would be to just "fake it"

#

you'd add a new kind of item spec -- maybe "key item spec"

#

like Key Items in a pokemon game

#

It would do absolutely nothing other than have a name and icon

#

The actual radar behavior would still be attached to the player

#

it would just check if you have an item that matches the radar item spec asset

dire elbow
#

Could I still make objects appear in front of the player? Like, if they have an upgrade in their left hand, it will show in front of them.

weary bobcat
#

You could reuse the item pickup prefab

#

or you could make something that literally just displays a model

#

conceptually, this is very similar to a hotbar slot

#

just with a model (or a different image) instead of the item's icon

dire elbow
#

What if I added model displaying to the HotbarSlot script. So that the Display method would instantiate a prefab from the ItemSpec in the slot selected. Then when you switch slots, it deleted the instance and replaces it with the prefab from the ItemSpec in the new selected slot.

weary bobcat
#

Yeah, that'd work.

dire elbow
#

Something like this. ```cs
public class HotbarSlot : MonoBehaviour {
[SerializeField] Image itemIconDisplay;
[SerializeField] Sprite defaultIcon;
ItemModel instance;

public void Display(ItemSpec itemSpec) {
Destroy(instance);
if (itemSpec != null) {
itemIconDisplay.sprite = itemSpec.icon;
instance = Instantiate(itemSpec.displayModel);
}
else {
itemIconDisplay.sprite = defaultIcon;
}
}
}```

dire elbow
dire elbow
dire elbow
dire elbow
# weary bobcat Yeah, that'd work.

I am no longer struggling with getting the GUI to function properly, however, I am struggling with getting the models to appear correctly. I am trying to create prefabs of objects via the HotbarSlot script, but for some reason objects arent deleting correctly and arent being generated at all. Here are my scripts:
HotbarSlot: https://hastebin.com/share/odikadetaw.csharp
Inventory: https://hastebin.com/share/uzifejuzom.csharp
ItemSpec: https://hastebin.com/share/ugakarawow.csharp

weary bobcat
#

if (leftHand.transform.childCount > 0) Destroy(leftHand.transform.GetChild(0).transform);

#

i would just store direct references to the spawned items

#

I would make a Hand component whose sole job is to show and hide items

#

HotbarSlot should not need to know how to deal with the prefabs

#

It can tell the Hand that it needs to show an item

#

You need to separate your concerns.

#

(although, really, I'd not have HotbarSlot care about hands at all)

dire elbow
dire elbow
#

I am currently testing it and have encountered an issue with the RefreshSlots() method. For some reason, the objects in the players left hand were updating late, while the right hand was working perfectly. Currently my solution is to put the RefreshSlots() method in FixedUpdate() so it is constantly updated, but not enough to slow down the game a whole lot.

dire elbow
weary bobcat
#

oops, sent that message in the totally wrong server lol

dire elbow
#

What I really like about this is the radars screen doesnt reset at all when the gun gets deleted and created in the other hand. Since the screen is a render texture it works perfectly.

#

And to get the objects to move around the player smoothy I created Hand objects that have the same RotateAroundPlayer script that the radar gun had. So the objects just get parented to the hands and move smoothly.

dire elbow
# weary bobcat nice (:

Is there a way I can check if the object in the players main hand is the radar, and only then allow the player to use upgrades?

#

So if the main hand is empty, the radar doesnt get upgraded. But if the RadarGun is in the players main hand and the player uses an upgrade in their offhand it does get upgraded.

dire elbow
# weary bobcat nice (:

Hi fen, I really need help with this. I can't seem to figure out how I can make the player able to drop items. I want the player to press G, and then the item in the currently selected slot will spawn the Pickup version of the object at the players feet. My problem is if the player picks up an item, I don't know how to store the physical item that was picked up.

weary bobcat
dire elbow
#

So, when the player picks the item up I set the item in the players currently selected slot to the item stored on the item picked up.

weary bobcat
#

and when you find an item in the world, you get the ItemSpec from the ItemPickup and put that in your inventory

dire elbow
#

That's exactly what I did :)

#

But, I added a little check that says if the ItemSpec doesn't have an item to spawn in the world, don't drop it, since if you drop it you can't pick it back up.

#

When I get home I'm going to rework the text so it displays on the UI instead of in world space.

#

I'm also going to figure out how I can make upgrades only get applied if the radar is equipped in the right hand.

weary bobcat
#

You could make UpgradeItemSpec abstract

#

and then create more specific specs for each kind of upgrade

#

(assuming you have more than one kind of thing you can upgrade)

#

either way, the Use method can check the item in your right hand

#

and just do nothing if it's incompatible

weary bobcat
#

this means you need an ItemSpec reference (which will be to the radar's ItemSpec asset)

#

so that you can check if, say...

player.rightHand.itemSpec == radarItemSpec

#

you'd have to assign this to each instance of UpgradeItemSpec