[Question] BIND_ACTION: passing parameters?

Is there a way to pass function parameters to the BIND_ACTION macro? Or some other workaround?

For example, I have the function…

	UFUNCTION()
	void SwitchToWeapon(uint8 WeaponNumber);

And I want to call something like this: (this doesn’t compiles)

	BIND_ACTION(InputComponent, "Weapon0", IE_Pressed, &AShooterCharacter::SwitchToWeapon(0));
	BIND_ACTION(InputComponent, "Weapon1", IE_Pressed, &AShooterCharacter::SwitchToWeapon(1));
	BIND_ACTION(InputComponent, "Weapon2", IE_Pressed, &AShooterCharacter::SwitchToWeapon(2));

We don’t currently have any way to bind parameters to be passed in to the delegate when it fires. It is something we are aware isn’t ideal, however given the many priorities we don’t feel it is overly onerous to have to create a unique delegate per key that then calls your shared parameterized implementation so it isn’t high on the priority list at the moment.

What do you try to accomplish ?

From what can I deduce here, you are trying to create inventory, which will store weapons. And then you assign key for each weapon on keyboard.
If that is the case, I have simple solution for you.

First create Inventory for your weapons, for example in you character class:

TArray WeaponInventory;

How do add weapon to the inventory, is whole another matter, not relevant the issue at hand.

Create input functions like:

void WeaponSlotOne()

void WeaponSlotTwo()

etc.

And properties:

Weapon* WeaponObjectOne

Weapon* WeaponObjectTwo

etc.

Now sample implmentation of these functions would be:

WeaponSlotOne()
{
APlayerController* PC = Cast(Controller);
if(PC)
{
ActionButtonOneObj->EquipWeapon();
}
}

Where EquipWeapon is function inside weapon class that set the weapon active.

You can assign WeaponObject like this:

void ACharacter::SetWeaponToActionBar()
{
		if(Inventory.Num() > 0)
		{
			for(AWeapon* weapon : Inventory)
			{
				if(weapon)
				{
					//we don't want to override already assigned object. So if it is null we pass
				//it's very bad way of doing this. I think.
					if(!WeaponObjectOne)
					{
						WeaponObjectOne = power;
					}
					else if (!WeaponObjectTwo)
					{
						WeaponObjectTwo = power;
					}
				}
			}
		}
}

It leave some place for randomness as you can’t predict order in which weapons will be stored in array.

To prevent that you can define enum in weapon, which will contain weapon types, and then instead of if, use switch, to assign weapon from array to the slot you want.

In blueprint you specify enum type for your class. And that class will be passed back to the code.

Thanks for the answer, but that’s not what I want. I want to write a single function to switch weapons (SwitchToWeapon(uint8 WeapNumber)), rather than one function for each weapon slot.

I know, each input function could just call SwitchToWeapon(number), but I wanted to keep the code clean (and scalable, for adding new weapons).

Then you should check ShooterExample. There is code for switching weapon with scroll wheel. I think it might be close to what you want.

Nah, that just returns the next/previous weapon on the list. And it’s one function for previous weapon and one function for next weapon. In other words, for what I want it should be SwitchToWeapon(CurWeap-1) and SwitchToWeapon(CurWeap+1). One function, not two (or 12, for what I want).

In any case I don’t see macro variant that would be able to pass parameters. For now on, you should go with the solution I posted (it’s not that bad, for example yesterday I saw something very similar used in Camelot Unchained, when one coder streamed his work on twitch).
In mean time you can create feature request for macro variant to take parametrized, functions.

You can check macro variants in InputComponent.h

I’ll do that for now then. I’ll just leave the question open, in case someone knows how to do that.

Or, if that’s currently impossible, please file my request, Epic. :slight_smile:

Actually you can use template parameters in such way:

void AChar::UseSlot(int slot)
{
 ...
}

template<int Index>
void AChar::UseSlot()
{
	UseSlot(Index);
}

void AChar::SetupPlayerInputComponent(class UInputComponent* InputComp)
{
	check(InputComp);

    InputComp->BindAction("UseSlot1", EInputEvent::IE_Pressed, this, &AChar::UseSlot<1>);
    InputComp->BindAction("UseSlot2", EInputEvent::IE_Pressed, this, &AChar::UseSlot<2>);
}

Hello,

This is a question from the beta version of the engine. We are marking this answered for tracking purposes. If you are experiencing an issue similar to this please post a new question.

Thank you.