Need Advice on Component Structuring (for an FPS)

I’m currently developing an FPS using the FP Template as a starting point. Currently, the gun behaviour (input and actions) is scripted within the main First Person Character Blueprint (as in the template). I would now like to migrate all weapon behaviours to a separate class/blueprint/whatever that I can reuse for different guns (that will be attached to the character).

I would like some assistance on how to go about this, keeping the following in mind :

  • The Gun Component will handle input directly, as well as all weapon behaviour will be described within the blueprint. Each gun has different inputs and firing behaviour, hence would like them to handle input on their own.
  • Weapon Visuals and FX will be housed within this component.

Sorry if this is a trivial question, but I’m unable to get clarity on what I should create, what options to check and how I attach this component to the character. Note that I’m using 4.21 on a Blueprints-only project.

Thanks,
Sel.

Not a trivial question at all, but I can only come up with reasons not to do this rather then reasons to do it.

For one, if you isolate the code you need to make every weapon it’s own blueprint/actor class =
extra overhead, and extra code that can go wrong.

For 2, even if you actually create a weapon actor class to replicate with a custom “movement component” that is not A movement component but rather parameters for firing, it sounds more cool then the end result would be, which is extra overhead and a bunch of cast to calls.

For 3, you would then need to talk back to the character animation blueprint for recoil or trigger pulls and such - depending on how high class of an FPS you want to make.

For 4, your projectile component still has to be independent as with a regular implementation, so you would still need all the same struts and parameters in place to handle quantity/velocity etc, living the heavy portion of the work the same regardless.

For 5, what happens if you press the button for firing a weapon that’s not currently in use but is in the level?
Even if attached the pawn owner is never the player or the controller, Ergo I don’t even think you could get it to fire without some creative cast to + custom event calls on it’s own blueprint.

I’m not sure what the benefits would be from having a more OOP version of a gun with it’s own base class and parameters.

Creating it properly in CPP with functions that you can just call (from the character) would be beneficial in terms of usability - but the button presses are generally speaking still all happening on the character controller because IT has input and not the gun.

Also, fire → cast to → call remote function might take longer than
fire → call function. Might, that’s something you should test before deciding if it’s worth to proceed…

if anyone can offer any reasons to or examples I would be greatly interested. It’s always good to learn new stuff.

Thanks for your detailed response. I am still a bit confused on how I could go about the implementation.

Say I have three weapons -

  • A Rifle that fires a single hitscan (raycast) on LMB and scopes in on RMB
  • A Cannon that fires projectiles on LMB and grenades on RMB
  • A Hybrid Machine Gun that fires bullets on LMB, launches grenades on RMB, and drops grenades on MouseWheel Down

I would like player to be able to switch between such weapons in the inventory. I felt having all the code within the character itself will result in heavy clutter in the character blueprint. Hence it made sense to me to dispatch the work to a weapon blueprint. In the end I’m just looking for a clean and optimal way to pull off what I’ve described above, and any guidance on that front is highly appreciated.

To streamline the event graph you should probably create custom events for each weapon firing mechanism and feed it off / reposition it wherever else.
Usually that already cleans up the noodle mess significantly.

Another way to keep order - just in general - is local variables. within functions particularly.

Yet another way to sort or handle things is Functions.

As far as I go, since I’m sort of coding something that is a close cousin to an FPS, I have my system set up with an array and a loop so that weapons can be cycled though. Like a standard FPS going from 0 to 9. The number in the array actually matches up the same offset of the keys on the keyboard… because why would anyone want to finagle with the array if you can just make it match?
here’s a sample.


Obviously the montage to play should be changed depending on the weapon, where it comes from where it’s attached etc. This is just a basic prototype and not what the final system would end up looking like if you are already dealing with sockets (I’m not for the moment still prototyping the right animations for movement).

Anyway, back to your actual question.

You have LMB, RMB, and MWD (mouse wheel down) as possible buttons.

You can drag off from any of inputs and immediately hand off to a custom function.
The function within the character blueprint will then handle all the logic of checking what is going on and how it should respond to the button press in it’s own event graph page without much mess on the main blueprint.
It would sort of be like passing it of to the weapon blueprint - but it doesn’t have any lag or necessary checking other than adding one function to the stack… Since unreal is still OOP it obviously handles the classic stack/function call system quite well.

Hope that helps. If it’s not enough or you want a different alternative that also allows more options, you could create a custom event and move it down like explained here:
https://docs.unrealengine.com/en-US/Engine/Blueprints/UserGuide/Events/Custom/index.html

I’m not sure how you would or if you could instantiate or call the event inside the weapon to keep the code with the weapon itself without some issues on slower systems, but if you are really set on doing it here you can find out how to call the events you set up from the character blueprint (and yes, somehow you still have to call them from the character bp).

Best of luck :slight_smile:

[USER=“3140864”]MostHost LA[/USER] In my case, those three aren’t the only inputs. I’m creating an FPS where there’s a greater focus on weapon operation than player movement and abilities. So there’re certain complex weapons with 6-7 controls with combo options across those controls. Wrt such a concept, don’t you think having all events possible for all weapons together, along with repsective switch-case setups might lead to heavy clutter? I do get your point on the merits of keeping it all within character blueprint, but I was hoping for a clean and manageable way to pull it off. Functions seem like they’ll help me with some cleanup, but I still don’t see how I can avoid that massive Input-event Bluuprint “Forest” in the character blueprint.

What you are essentially looking for is a modular weapons functionality. You can use BP interfaces, say something called BPI_GunFunctions. From here, you control all native functionality on the player pawn event graph, while gun specific functions can be passed on to the gun BP via the interface.

Yea, but like he said the button press checks are still going to be a lot of branches right on that main graph…
I dont really see a viable alternative though. Specially since the gun doesn’t have a controller associated to it and even if it did, it would not be the active actor to receive input…
Maybe someone has a work around for that though…

Well, not really. You have a switch that essentially sends the button press over the interface, regardless of whether the receiving object uses it or not. Say Left click, middle click and right click are sent to the interface regardless of what gun one is holding. Then within the gun BP, if the function is implemented, it runs to throw grenade/shoot/self destruct. The conditional code for receiving an input should anyway be on a player pawn regardless of what you are trying to achieve.

So to the OP,

Say you have action 1 through 20. These are button clicks/scrolls/keyboard head bang and what not.
For each of these actions/ input events, you add an event to a new BP interface. You will have events named as Action1 with some input variables, Action 2 with some more input variables. You can also have Action 3, that comprises of both Action 3 and 4 off a float/boolean value for things like scroll up/down. So on and so forth.

Once you call these BP interface events (after a Does Implement Interface node) on the actual inputs. You essentially are left with events firing off for only the guns or whatever you want to use. These events are fired off within the Gun’s individual BP’s and can be bound to anything you want. Yes, the player pawn graph will be a tad (just a tad) messy, but theres no way around that. It would actually be a lot simpler than most of the things we do here.

So now you have your event calling setup. Go to your Gun BP, add the interface, and it will give you all the event handlers. Use these for any per gun customization you may need.

Thanks for your response @Hereafter. It’s still a bit of a shame that I can’t avoid the mess in the player graph, especially since I considered my weapons radically different enough to be considered separate classes outright. Either way, I’ll try to work out an approach as clean as possible.

The character and gun will always be dependent on one another eg. the gun has to know if the character is dead or incapacitated etc. while the character needs to know what it is currently doing with the gun eg. is it shooting? reloading? idle?

It might be tempting to place everything on the Character and have the Character call the Gun through an Interface but as you already know the Character has a ton of things to do and quickly becomes a huge mess of functions. Why not let the Gun handle any Gun specific Input Actions and give it a hard reference to the Character so it can easily check the state of the Character, bind to important Character Event Dispatchers and let the Gun call Gun related functions on the Character directly when necessary.

You possibly also need an Inventory that can pickup, drop and select the weapons. If there is any context sensitive input however things get more complicated.