where do i put my code? playercontroller or in the pawn/actor itself?

just wondering.

i started looking through some inventory projects and it seems like they are all putting stats and functions of the inventory into the player controller.

i have however been writing things like stats, combat and inventory into the pawn/actor itself.

also i eventually want to create child of the pawn/actor and set them as npc/enemies so how would i go around making them if these are in the player controller?

would the enemy/npc be able to access the code for attacking, sensing and have their own inventories if i put my code in the player controller?

thanks!

Interesting question, I’d like to know the best answer for myself too!
There are many ways to receive the same result, sometimes different paths are better for your particular type of game.

I’m not the most experienced person but since there are no replies, I’ll toss in my 2 cents :slight_smile:

Not entirely sure why you’d want to put things directly into the player controller, unless you were handling local multiplayer or having the player control different pawns throughout the game.

I think it would be perfectly reasonable to put things like Combat functions or some Variables inside the actor. For things like health I typically would store that inside of a Game Instance so I can use it across different maps storing the same state.
In your case for making an enemy/npc it would be easier for you to make an AI Controller class and have it call functions from its Actor/Pawn class as it would be a good use of Class Inheritance.

One of the reasons is respawning. If you destroy the actor, becuase it dies and you create a new one all your player stats, inventory, things you keep on the pawn will be reset. It makes much sense to keep it on a player controller, or player state. Also, if you want to control another pawn from the same player controller, let’s say your character change into a monster, which is a different pawn, the inventory will be still accessible, because it’s not part of the pawn. There are many other factors, how to design your game, there is no one single good solution.

3 Likes

Eanir is correct, there are so many different variables that will determine what goes where.

The key thing to think about is re-usability. If you’re planning on using your Pawn class to create child actors with an AI controller but the AI are going to have all the same functionality as your player pawn, then keeping the inventory, stats, etc. in the Pawn class is fine since the AI child actors will inherit and have all of the same functionality as your players.

Typically I try and treat my Pawn as the “body” and the Controller as the “mind”. My mind doesn’t hold inventory, so my inventory stuff is on the pawn - but this means if my pawn dies, they lose their inventory (unless I store it temporarily somewhere else) but I’m a toxic developer and have no mercy so I spit out their items on the ground and call it a day :stuck_out_tongue:

Movement logic also exists on my pawn. If my pawn is dead, WASD / Space / Interact means nothing to my controller. This is a pretty nice benefit since I don’t have to have a bunch of **Pawn **-> IsValid checks on my Controller.

UI stuff is on my controller though because if my pawn dies, I want my controller to be able to still click around / go back to lobby / rage quit. etc.

This is one of those “it all depends” type answers lol :rolleyes:

3 Likes

You can always make a new actor component and add your inventory to that instead, so you’d have an inventory component you’d now be more easily able to swap to different classes depending on whether it needs it or not. It all depends on your needs and what makes sense to you for your overall hierarchy.

A child of a neutral class could for example have a bool in the parent of isEnemy, with the child just having it to true as an easy example and a friendly box having it to false. You can also inherit or override functions/events.

Bingo - even more re-usable. That way you can simply attach the component to whatever actor(s) need an inventory - your players, AI, zombies, cars, bears? Can bears have inventory? :rolleyes:

The actual answer is - Player State. It’s specifically made for holding the… current state of the player.

1 Like

@DamirH I’m curious about your answer. Since the Player State is replicated to all clients, it’s useful for something like player name, kills/death, score, level, etc. if you want that information about your player to be visible to other clients. What’s the purpose of putting something like the inventory in the Player State? i.e. Why would other players need to know what you’re carrying? Unless that’s what you intended, I guess.

I would stick on using different components just for the sake of modularity. Following @BRY reasoning, I would just implement the character stuff in the character, such as movement related inputs and so, and would use the player controller for more general stuff like UI interacction. Another reason to do this would be the fact that you might want to change the controlled pawn at some point of the game to another with different functionalities (like getting into a car or stuff like that).

Either way, you should not worry about this if you are not aiming at something scalable. In small stuff as in game-jams I just go with whatever I feel that does the trick.

Indeed when it comes to a multiplayer game the player state is questionable depending on whether or not you need to have all other players see your inventory (thinking of something like Mario Party). If it were an MMO game where your inventory is only between you and the server, the player controller is what you want, because in most games your pawn will change (if we take for example World of Warcraft, your character and your mount might be two pawns that you switch control in-between) but your inventory needs to be available on both.

2 Likes

Ah, I see, I didn’t think about mounts… great example! Thanks for the clarification :smiley:

One thing about the component suggestion - be careful about component-creep. This isn’t Unity, making everything a component isn’t the preferred design paradigm. In the end you end up having more “glue” code than gameplay code for one. But more importantly, every component is a UObject that needs to be instantiated and whose lifetime needs to be managed etc. which is not really cheap. If we use an MMO as an example again, just think of the server having to manage 10k players - if you make your inventory a component that’s 10k additional UObjects to keep in instantiate, keep in memory, check for GC etc.

For much more than just this specific situation, I’ve come to believe strongly in the compositional design pattern – that is, single-purpose components that can coexist on a single Actor.

My previous design pattern was inheritance-driven, with everything in subclasses, and I still do use inheritance, but for data types and not for functional partitioning. The distinction is subtle but it matters for code reusability.