Anyone understand the input flow? Can I hook it to for a weapon as well as a player?

Trying to handle weapon input (fire selector switch, various input movement stuff) within the weapon itself. Currently all input in shootergame is passed from the character class, which annoys the **** out of me.

Is it possible to have a character AND a weapon handle input? I really want the input path on the weapon to be available to blueprint too. Anyone seen that? probably a checkbox somewhere right?

You taught me how to use behavior trees, so I’m glad I can repay the favor. High level overview: UInputComponents hold the action or axis bindings that can be called on a specific actor. APlayerController is the main organizer of player input, it builds the input stack every frame. The input stack is just an array of UInputComponent* that defines the order in which each input component will be processed, based on their priority. The input components that will appear on this stack are (in order of ascending priority): The controlled pawn, Level script actors with input enabled, the controllers input component, and then an array of input components that can be manually added to with APlayerController::PushInputComponent(UInputComponent InputComponent)*. The stack of input components is given to a UPlayerInput subobject of the player controller, and this subobject will organize input and execute the bound delegates. Note that if a binding has not been manually set to not consume input, any input components below it on the stack that also have a binding for that input action/axis will not receive the event (you can set the binding to not consume input by doing InputComponent->BindAction(…).bConsumeInput = false; when you set up the binds. This might be useful if say, you want your pawn to know about shooting input as well as your weapon actor).

The way you will probably want to set it up is with the weapon right at the bottom of the stack, after the pawn. To do this you’ll need a custom player controller to override void APlayerController::BuildInputStack(TArray<UInputComponent>& InputStack)* and push your weapons input component onto the stack first, and only then call the Super::BuildInputStack. By default, your weapon will not have an input component, so you’ll have to create one when your weapon is equipped and wants to start accepting input. You shouldn’t use AActor::EnableInput(APlayerController PlayerController)* to create your input component because that will also push the component on the controllers manual stack, so you should use your own enable input function that only copies how AActor creates the component and then does the blueprint bindings.

Normally you would use SetupPlayerInputComponent() on your pawn to actually bind to functions, but your weapon obviously doesn’t have that function. However, it should be as simple as calling InputComponent->BindAction(…) in the Equipped() function of your weapon.



//this function is called every frame and determines what input components will receive input events
void AMyController::BuildInputStack(TArray<UInputComponent*>& InputStack){
	AMyPawn* ControlledPawn = Cast<AMyPawn>(GetPawnOrSpectator());
	if (ControlledPawn){
		//get the current weapon that we want to send input to
		AMyWeapon *EquippedWeapon = ControlledPawn->GetCurrentWeapon();
		if (EquippedWeapon->InputComponent)
			//if it has an input component then push it to the bottom of the stack, before everything else
			InputStack.Push(EquippedWeapon->InputComponent);
	}
	//now put all the other input components on top
	Super::BuildInputStack(InputStack);
}



void AMyWeapon::OnEquipped(){
	//copied from AActor::EnableInput, creates input component and binds blueprint actions, but without pushing it onto the controllers manual stack
	if (!InputComponent)
	{
		InputComponent = ConstructObject<UInputComponent>(UInputComponent::StaticClass(), this);
		InputComponent->RegisterComponent();
		InputComponent->bBlockInput = bBlockInput;
		InputComponent->Priority = InputPriority;

		UBlueprintGeneratedClass* BGClass = Cast<UBlueprintGeneratedClass>(GetClass());
		if (BGClass != NULL)
		{
			UInputDelegateBinding::BindInputDelegates(BGClass, InputComponent);
		}
	}
	//notice missing PlayerController->PushInputComponent(InputComponent);

	//you can do input bindings 
	InputComponent->BindAction("Fire", IE_Pressed, this, &AMyWeapon::Fire);

	//when the weapon is unequipped you can set InputComponent = nullptr; and it will stop receiving input immediately
	//I forgot to add that you will have to sort out a mechanism to either re-use the existing component or destroy it otherwise you'll end
	//up creating more and more unused input components every time you switch weapons. This is just a general object management thing
	//that I didn't think about until later.
}


I haven’t tested this code but it should work.

This code is very simple and inflexible, you might want to make a custom controller that uses a more general approach, like another manual input component array that you apply before everything else in the stack, instead of limiting yourself to subclasses of weapon actors.

4 Likes

That is some serius great information right there mate :slight_smile:
Cheers!

Thanks Beej, its this kind of information that really makes developing easier.

The more we share, the more we learn :slight_smile:

Thanks for sharing! I was looking for the knowledge to wrap my head around the input system in UE4. This helps a lot.