Better way to achieve semi-automatic fire for third person shooter?

I’m trying to implement a weapon system into a third person game. Each weapon is a child of a master weapon blueprint, which has common variables and functions that its children would inherit, and overwrite when needed. But now I need to define each weapon from its siblings and parent.

  • Automatic weapons should fire for as long as the input is held (and ammo avilable).
  • Semi-automatic weapons should fire only once per input trigger.
  • Charged weapons increase a “Charge” variable value for as long as the input is held, and once reaching 100, fires and resets the value.

Semi-automatic weapons are where I’m facing trouble.

If I fire a semi-auto weapon and keep the input trigger held, I only fire one shot; it’s working as intended. But if I release the trigger and hold it again inside the timer, I fire a shot second shot as soon as the timer is complete; this is not ideal.

I’ve included the relevant parts of the event graph and functions below.

Event Graph


Semi-auto

DelayComplete function called at timer end
Delay

I’m relatively new to Unreal Engine and I’m using the latest build, 5.1, which came with the Enhanced Input Action system. If it’s relevant to the problem, the current “Fire” input trigger is the Left Mouse Button on default settings (Down).

Is anyone able to help?

It probably makes sense to set the trigger held bool, the moment the trigger is actually held?

“TriggerHeld” is a bit of a misnomer; I should’ve called it something else. In this case it referred to the physical gun trigger, rather than the input. What it’s actually doing is keeping a track if the button is still being held since the previous “shot” has been fired.

I really don’t know if I’m doing any of this right, but this is the way to achieve semi-auto functionality as it’s currently implemented.

Thing is, those three routines ( for each type of gun ) really need to get a signal when the trigger is pulled, and when it’s released. And that really is ‘mouse down’ / ‘mouse up’ ( or controller etc ).

Then they can respond differently internally, based on the type of gun.

2 Likes

Isn’t that the same as the “Completed” pin on the input event node?

It seems you are calling “PullTrigger” constantly while the trigger is held.
Thus you need to block the the firing ability of SemiAuto weapons if you press the trigger and it failed to fire (because you were in Delay the moment you pressed) until you “ReleaseTrigger”.

How might I do that?

DoOnce node :slight_smile:

I think you’ve been close to finishing this,
you need to set InDelay variable to True after firing and before timer in SemiAuto.
In the DelayComplete function reset InDelay bool to false.

This should do the trick.

Edit: reset the bool in ReleaseTrigger, not in DelayComplete.

I think DoOnce state will reset inside the function?
It will work outside of it though. My bad.

Like so?

It all needs to happen in the function, I think… :slight_smile:

Apparently not, it’s working fine outside. That being said, I presume there’s a reason why I’d want it to be inside, not just part of the event graph?

When a function is called, it doesn’t save it’s state from its previous call. So DoOnce node will reset as well. ))

In my opinion, not really. it’s mostly because it’s a bit noodle-like, so I usually prefer bools and branches to control the conditional execution flow. Also in this case it’s an exception for one type of weapons and located outside of the said weapon main logic, so it probably doesn’t look as neat as it could be.

I normally use a timer for all kind of shooting and timing, semi-auto could look like this:

Firerate is max shots per second.

But I wouldn’t pack all firing modes into the master - does every gun really need to know how to shoot in every mode? That enumerator switch seems redundant. You tell a child to fire and the child interprets that call in their own way.

If I needed modular guns, or guns with multiple firing modes, I’d have the firing mechanics in an actor component instead. You give the specific children their specific firing modes. It’s probably irrelevant if you 3 modes and 10 guns but becomes very relevant if you’re making Borderlands 5.


Admittedly, there will be as many semi-auto methods as there are people in the thread. :innocent:

2 Likes

I see what you mean about children not needing to know about the logic of their siblings, and I currently only plan to have the three firing modes listed in the first post for eight guns (Pistol, SMG, DMR, Assault Rifle, Shotgun, LMG, Sniper Rifle and Railgun). The enumerator was just all I could think of with my limited experience.

When should I use an Actor Component instead of an Actor Blueprint, and what variables and functions should be a part of it? That’s entirely new to me.

But your proposed graph only solves half the problem: it’s much cleaner than mine (thank you so much!), but essentially makes all guns fully automatic if you don’t take your finger off the input trigger, just with slower fire rates. I suppose Do Once should be included?

Then you have an issue with the way you handle input itself as well. I am not even talking about enhanced input here. The most basic key down works for the above, and that’s without utilising Released:

image

Try it out with the suggested script.


Also, Timer works great if you need things to work really fast and be frame independent. As in consistently fire multiple shots in a single frame. The distribution over a single frame is somewhat weird but can be ignored in 99% of cases.

Not trying to convince anyone this is the best method evah. That’s the best method I know, because someone else did a lot of trial and even more errors, and settled for it. Worked for me, too.


I see what you mean about children not needing to know about the logic of their siblings, and I currently only plan to have the three firing modes listed in the first post for eight guns (Pistol, SMG, DMR, Assault Rifle, Shotgun, LMG, Sniper Rifle and Railgun). The enumerator was just all I could think of with my limited experience.

If that’s the scope and the guns cannot be modified drastically run-time, then I’d have a fire function in the parent and override in the child.


When it comes to actor components, folks do not give them nowhere near enough credit. Think of them as of chunks of functionality you add to or remove from actors, during run-time, too. An actor does not need to know upfront what it’s capable of doing later on. They support inheritance:

image

An actor can have many comps, each with a graph, variables and functions (not timelines, though):

You can even overrride a Static Mesh Component which are highly specialised Actor Component everybody is familiar with. This way each gun part can already handle a mesh, material, animations (skeletal), collision…

Let’s say you have 100 guns and 12 scopes, some guns have it, some don’t, we don’t know, not yet. The player holding a gun actor evokes Press X to Use Scope via an Interface:

  • base gun class actor - do we even have a scope:

image

  • child gun actor:

If this particular child has a scope, we use the scope’s functionality. If you now spawn 100 guns, only the 25 that have one of the 12 scopes will have the functionality.

If I have a grenade_class_gun, I will not even bother overriding UseScope, because the component that could perform the action make no sense for a grenade. But the grenade could have a component that deals splash damage a pistol would never care about. Your base gun actor should never care about what splash damage is.

What you end up with is a much lighter base gun class that has no idea what is going on, a child actor that knows a little bit more and functionality that is compartmentalised, encapsulated in a component and evoked only when needed.

Another good example is fantasy-like setup where the player can learn 600 spells. You do not want to spawn the player with 600 spells. You add spell component as the player learns them. You definitely do not want an enumerator with 600 entries.


The above is somewhat crude and still incomplete because you need the comps to talk back to the owning actors - another interface or dispatchers work great here.

Essentially, if you ever need to build a huge freaking robot, where limbs have sockets for multiple weapons and each one is different and moddable, actor components are an outlet for that.

1 Like

I see. So are you saying it’s better to determine input triggers and their behaviour inside the blueprints instead of the Input Mapping Context?

To be clear, the Input Event is in the Third Person Character blueprint, which is then sent to the weapon master.

How do I create a fully automatic weapon with the same logic, then? And again, when and how should I use an Actor Component instead of the Actor Blueprint itself?

1 Like

We cross-posted, updated above.