Newbie Question: Need help with InputComponent->BindKey (I think)

Hi there, I’m pretty new to c++ programming, especially in Unreal, but I’m fairly well versed in blueprints. I’m trying to learn more c++ so I figured I would attempt to implement simple sprint function using the base Third Person C++ template, but I’m apparently doing something wrong and I can’t figure out what.

The equivalent in blueprints would be to use a key press/release node for something like Left Shift and then modify the player’s speed. That would only take about a minute or so to setup in blueprints. For the c++ side of things, I was doing some research and I saw people say the equivalent is

InputComponent->BindKey(EKeys::A, IE_Released, this, &Controller::AReleased);

I’ve also seen some people use BindAction, but for this I’d rather not have to go and set bindings inside of the editor. I’ve only found a couple of code snippets that people have posted and so I’ve been trying to piece things together, but no matter what combinations I’ve tried, I keep getting errors.

What I have so far in the header file is:
PlayerSpeed- a float that will keep track of the player’s speed
isSprinting- a bool that will track if the player is sprinting (for event ticks later)

What I have so far in the source file is:
BeginPlay()- an event that sets the PlayerSpeed variable to the default MaxWalkSpeed value at the start.

What I need now:

  1. A key press/release event that toggles isSprinting between true and false.
  2. A tick event that sets MaxWalkSpeed equal to PlayerSpeed * 2 when sprinting and PlayerSpeed / 2 when they stop sprinting.

I’m just struggling with the Unreal API and where some of these things are located and how to implement them because all of the stuff is located in one place in Blueprints. Any help would be greatly appreciated.

You’re on the right track.

First up, whilst BindKey is valid, you might find BindAction to be more convinient when it comes to allowing custom controller setups, or when deciding you want to change which key / button performs the action (with a binding, just change it in the editor rather than having to find each case). Obviously it’s your choice and there are ways of achieving whatever you want with both methods, so go with whatever you like (it’s fairly trivial to change later down the line if needed).

So, taking your example:

InputComponent->BindKey(EKeys::A, IE_Released, this, &Controller::AReleased);

This will perform an action when the A key is released. You can change to IE_Pressed (I think) to perform some action when the key is pressed. Having one binding for pressed and another for release makes it easy to control things like ‘hold shift to run’.

The fourth param in your binding has some issues though. You need to replace &Controller with the name of your class where the bound mthod can be found. In your case it looks like &AtestcodingprojectCharacter. You then need to provide a method name. I’d suggest &AtestcodingprojectCharacter::OnSprintReleased. You can also use &ThisClass::OnSprintReleased.

Next up you need to actually create your OnAReleased method. In your .h file make a new protected or private method (it can be public, but nothing else should ever really call this method so best to protect it)

UFUNCTION()
void OnSprintReleased();

Now in your cpp, implement that method

void AtestcodingprojectCharacter::OnSprintReleased()
{
//your code in here
}

Hopefully that’s set you up with the binding events.

To toggle a sprint you should make another binding but using IE_Pressed and a new method OnSprintPressed.

Now you have your two methods you can either use a bool to track the state (which you just set to true or false in the methods you just created), but my prefered way would be to directly set the movement speed, thereby avoiding any tick processing. Something like:

GetCharacterMovement()->MaxWalkSpeed = whatever_you_want_the_speed_to_be;

Just have one of them in the OnSprintPressed and another in OnSprintReleased. Ideally you’d have the two desired speeds setup as editable, but hardcoding for now will get you going.

Hey, thanks for the extremely detailed response. That break down helped out a lot. And yeah, you’re right, using the event tick in this case is unnecessary.

I got everything set up, but I ran into an odd error that doesn’t seem like an Unreal error when compiling. At least it’s not anything that I ran into before. It doesn’t give a line number or anything, but after commenting out some of my changes, it’s the two InputComponent lines that are causing it.

I tried compiling inside of Visual Studio. It still had the error with the same text, but this time it actually gave me a link for the error LNK2019. I looked it up but I am lost on how to address this error here. [Here is the link][1].
Here is the specific error text:

2>testcodingprojectCharacter.cpp.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __cdecl FInputChord::FInputChord(struct FKey,bool,bool,bool,bool)" (__imp_??0FInputChord@@QEAA@UFKey@@_N111@Z) referenced in function "protected: __cdecl AtestcodingprojectCharacter::AtestcodingprojectCharacter(void)" (??0AtestcodingprojectCharacter@@IEAA@XZ)

Just in case the error has to do with referencing another piece of code that’s bad somehow, I’ll include that as well.
The stuff in the header file:

The functions at the bottom of the source file:

The actual InputComponent stuff using the F key instead of A:

Glad it helped! For your new error, my guess would be a dependency problem (meaning your project doesn’t recognise what your asking it to do because you haven’t told it to use certain modules - in other words it can’t link code together). A quick google suggests that this might be the answer though: Why does BindKey cause Link error? - C++ Programming - Unreal Engine Forums

Oops, the thread hadn’t updated when I posted this comment. I did try that solution but for some reason it just causes unreal to crash and the project won’t open until I remove the additions and recompile.

So perhaps I should just try the BindAction version if this is going to give me so many issues that I wasn’t expecting haha.

If unreal crashes when you add those dependencies it’s likely that you’ve made an error in the Build.cs file. Slate and SlateCore are pretty common to add. Can you paste that section of your Build.cs so I can see if there is an issue?

Edit: Wrote uproject when I meant build.cs

Sure, here’s the edited Build.cs file.
using UnrealBuildTool;

public class testcodingproject : ModuleRules
{
	public testcodingproject(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;

		PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay", "SlateCore", "Slate" });
	}
}

I did also try with an extra “,” at the end like the example had just in case, but same issue. I did notice that if I commented out the InputComponent lines in the character source file, it built successfully and I could open the project again. But once I brought those back into play, it would crash.

As far as these dependencies, is adding them pretty normal for a lot of projects? Or is there any way to default to having them included when creating a project?

The Build.cs looks fine and yes, as far as I know it’s pretty common to add dependencies in projects. Sometimes it’ll be things like Slate and UMG, other times it’s going to be a plugin specific to your project.

I’ve just tried using BindKey in my project and it compiles fine. Does your error out in compilation or is it only when attempting to open the editor? It might be worth right clicking on the UProject file and regenerating the VS solution, then compiling from within VS to see if that helps.

Ah, that might be it. I setup mine in SetupPlayerInputComponent which is a virtual method from APawn. Assuming your character class inherits from APawn or ACharacter too then put this in your .h (protected)

virtual void SetupPlayerInputComponent(UInputComponent* InputComponent) override;

and then implement it in your CPP.

I think if you want to setup in your player controller rather than a character you can use SetupInputComponent(UInputComponent* InputComponent) instead;

You shouldn’t need to call any of these methods yourself, UE4 will do that for you as part of the character / controller initialisation.

Maybe I’m just putting the BindKey lines in the wrong place?

I uncommented the InputComponent lines and attempted to build inside of Visual Studio. It said 1 succeeded and 1 skipped, but no errors popped up. However trying to open the project still crashes before opening at around 71%. I also tried the right-click and did the generate files option. It did it’s thing and I tried opening the project but it still crashed like it has been.

I’m going to try creating a new project from scratch and recreate the variables, functions, and things to see if that works

Ahh ok. Yeah. I recreated everything and put the lines inside SetupPlayerInputComponent and it compiles and I can run around and sprint. I originally had it in there but tried moving it when I was attempting to fix the LNK2019 error.

There is one more small issue, but it’s unrelated. I had to comment out my BeginPlay function, even if it’s empty. Everything still compiles and I can hit Play in the editor and test, but the character is frozen, won’t even play the idle animation. As soon as I comment out BeginPlay() in the header and source file, I can run around and sprint. I’ll figure that out though.

Thanks so much for helping me get this worked out though. I really appreciate it.

Edit: All I had to do was add Super::BeginPlay(); in the source file and that fixed the frozen character issue.

I was about to suggest that you add Super::BeginPlay(). When you’re overriding virtual functions it usually a good idea to call the base class method (Super) at somepoint as it’ll normally be performing some additoinal functionality. If you don’t add it then it’ll only ever execute the code you provide and ignore everything else in the base class.