x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

SetupInputComponent in PlayerController

Hello,

I know there's already a lot of threads explaining how to setup inputs in the playercontroller to move my pawn, but I tried to do so but I still can't manage to make it work. I've made a new PlayerController class, called CampaignPlayerController and I've also made a new public function, which is virtual void SetupInputComponent() override. Here's my .h file for my controller:

 // Fill out your copyright notice in the Description page of Project Settings.
 
 #pragma once
 
 #include "CoreMinimal.h"
 #include "GameFramework/PlayerController.h"
 #include "CampaignPlayerController.generated.h"
 
 /**
  * 
  */
 UCLASS()
 class PRIMALWARS_API ACampaignPlayerController : public APlayerController
 {
     GENERATED_BODY()
 
 public:
 
     ACampaignPlayerController();
     
 protected:
 
 
 
 public:
 
     virtual void SetupInputComponent() override;
     
 };
 

And here's my .cpp file:

 // Fill out your copyright notice in the Description page of Project Settings.
 
 #include "Controllers/CampaignPlayerController.h"
 #include "Characters/CharacterBase.h"
 
 
 
 ACampaignPlayerController::ACampaignPlayerController()
 {
     // Sets default values
 
 }
 
 void ACampaignPlayerController::SetupInputComponent()
 {
     Super::SetupInputComponent();
 
     InputComponent->BindAxis("MoveForward", this, &ACharacterBase::MoveForward);
     InputComponent->BindAxis("MoveRight", this, &ACharacterBase::MoveRight);
 
     InputComponent->BindAxis("LookUp", this, &ACharacterBase::AddControllerPitchInput);
     InputComponent->BindAxis("LookRight", this, &ACharacterBase::AddControllerYawInput);
 }

Also, the functions MoveForward() and MoveRight() are defined in my Character-class. I'm simply trying to move my character using the player controller that I've made. How do I do this? The code above doesn't work and gives me red underlines my super-call, and gives me an error saying:

 FInputAxisBinding &UInputComponent::BindAxis(const FName)': cannot convert argument 3 
     from 'void (__cdecl ACharacterBase::* )(float)' to 'void (__cdecl ACampaignPlayerController::* )(float)


If anyone could help me it would be highly appreciated! Thanks in advance :)

~Stefan

Product Version: UE 4.20
Tags:
more ▼

asked Nov 06 '18 at 03:03 PM in C++ Programming

avatar image

Steferich
104 4 7 8

(comments are locked)
10|2000 characters needed characters left

1 answer: sort voted first

I think your issue may be that you're trying to call up a function belonging to a different class. Usually, you provide the BindAxis macro with a function also belonging to your PlayerController class.

This explains the compile error you're getting: the compiler is telling you it cannot cast (convert) ACharacterBase to ACampaignPlayerController. It's expecting a function belonging to the ACampaignPlayerController class.

Here's another way of thinking about it. The way you have it set up right now, your PlayerController does not know which instance of ACharacterBase to execute the move functions for. You're telling it, "When move-forward input is provided, execute the MoveForward function on the APlayerBase class." But which APlayerBase actor should the player controller call this function on? See what I mean?

Try making a pair of new functions in your ACampaignPlayerController class, also called MoveForward() and MoveRight() if you want, and direct your BindAxis macros to those functions instead.

Then, from within the new movement functions, call up the existing MoveForward() and MoveRight() functions on your APlayerBase class using a pointer to specify which specific APlayerBase actor you want to respond to the input.

That should get things moving for you. (See what I did there?)

Best of luck!

more ▼

answered Nov 06 '18 at 06:09 PM

avatar image

the_batch
1.1k 4 5 8

avatar image the_batch Nov 06 '18 at 06:16 PM

Also, I forgot to mention, the red squiggly underlines you're seeing on your Super call are a known but harmless issue that started in UE 4.20. Starting with that version, Visual Studio seems to get confused by the many UE macros throughout the codebase and seems to think many publicly accessible members are suddenly not publicly accessible.

It's annoying to ignore and work around, but I'm not aware of any fix. Luckily, it doesn't actually interfere with compiling. Just Intellisense being weird.

avatar image Steferich Nov 08 '18 at 07:06 PM

Hello! I understand what you're saying, but I'm struggling to implement this into code. First of all, I've made a new variable in my .h of my controller

 ACharacterBase* PossessedPlayer;

and set it to the player that my controller is possessing using a cast in my controller's construct:

 // Sets default values
 ACampaignPlayerController::ACampaignPlayerController()
 {
     PossessedPlayer = Cast<ACharacterBase>(Player);
 }

If you didn't know, Player is the player that is possessed by the controller, I found this is the APlayerController API.

I've then tried to use my function MoveForward() to add movement input by calling AddMovementInput from my character, or the player that is controlled:

void ACampaignPlayerController::MoveForward(float Value) { if (PossessedPlayer) { PossessedPlayer->AddMovementInput(PossessedPlayer->GetActorForwardVector() * Value); } } Anyways, this doesn't work, and it has definetily got something to do with me trying to reference the respective controlled player of my controller. Adding mouse look/input works completely fine however, here's the InputComponent function in my PlayerController:

void ACampaignPlayerController::SetupInputComponent() { Super::SetupInputComponent();

 InputComponent->BindAxis("MoveForward", this, &ACampaignPlayerController::MoveForward);
 InputComponent->BindAxis("MoveRight", this, &ACampaignPlayerController::MoveRight);

 InputComponent->BindAxis("LookUp", this, &ACampaignPlayerController::AddPitchInput);
 InputComponent->BindAxis("LookRight", this, &ACampaignPlayerController::AddYawInput);

}

If you have any ideas, please let me know. Thanks for the great support, I really appreciate it! :)

avatar image the_batch Nov 09 '18 at 04:41 PM

If your character is responding to look input, that's good — it means that your pointer to the controlled character is non-null (which would have been my first guess).

My only remaining guess right now for why movement input isn't working is: does your ACharacterBase class derive from either the ADefaultPawn or ACharacter built-in classes? It needs to if you want AddMovementInput() to work automatically. Check out the UE documentation page for AddMovementInput(...) to see this note at the top about using those two classes versus implementing your own behavior to handle movement:

Base Pawn classes won't automatically apply movement, it's up to the user to do so in a Tick event. Subclasses such as Character and DefaultPawn automatically handle this input and move.

If the name of your character class is any indication, though, it seems you're probably already deriving from ACharacter, in which case I'm not sure why it's not working. Just thought I'd check.

avatar image Steferich Nov 09 '18 at 05:03 PM

My ACharacterBase is derived from ACharacter, yes. And the mouse look is all handled in my player controller with AddPitchInput and AddYawInput, in which I won't need to reference my character in any way.

In fact, I recently found out my controlled character is null, and just don't know how to set it. From there, I should be fine figuring things out. So, any clues?

Again, thank you so much for your help :)

avatar image the_batch Nov 09 '18 at 06:17 PM

Sure. Here's one way I've used in the past.

You can override the APawn::PossessedBy function to know when your pawn has been possessed by your player controller.

In your ACharacterBase.h file, you can override this function function like so:

 // Called whenever this character is possessed by a controller
 virtual void PossessedBy(AController* inController) override;

Also in ACharacterBase.h, you might also want to define a pointer to store the player controller that possesses the pawn:

 // A pointer to the campaign player controller that has possessed this character:
 ACampaignPlayerController* CampaignPlayerController;

Now in your ACharacterBase.cpp file, define PossessedBy using something like:

 void ACharacterBase::PossessedBy(AController* inController)
 {
     ACampaignPlayerController* CPC = Cast<ACampaignPlayerController>(inController);
     if (CPC)
     {
         // Store a pointer to the campaign player controller for convenience:
         CampaignPlayerController = CPC;

         // Now call up OnPossess on the campaign player controller, providing it a
         //  pointer to this character so the controller can later access it easily:
         CPC->OnPossess(this);
     }
 }

Next, in ACampaignPlayerController.h, define a pointer to the ACharacterBase actor that will be possessed, so the controller always has a way to access the controlled pawn:

 // A pointer to the controlled pawn so it can be easily accessed once possessed:
 ACharacterBase* ControlledCharacter;

Finally, you can define your OnPossess function in ACampaignPlayerController.cpp like so:

 void ACampaignPlayerController::OnPossess(ACharacterBase* inCharacter)
 {
     // Just possessed a pawn. Store the pointer to it for later use:
     ControlledCharacter = inCharacter;
 }

That's it! Your controller will now always have a pointer to the controlled pawn, even if the controller switches from pawn to pawn.

Hope this helps!

avatar image the_batch Nov 10 '18 at 01:37 AM

Follow up: I'm very dumb. I just realized there's a GetPawn() function on the AController class.

So, instead of all that work above, just try calling GetPawn(). You can call this and cast it once, for example in your BeginPlay() function, and from then on you'll have a pointer to your ACharacterBase actor that you can use for all of your movement inputs.

Can't believe I overlooked that. Oh well. Now we know!

avatar image Steferich Nov 10 '18 at 07:51 AM

Actually, when I think about it, I tried to set my PossessedPlayer in my constructor, whereas the possessed pawn isn't even set before begin play! Dunno what I was thinking, but anyways, your solution works fluidly, I'm so glad right now :3

Thank you so much, the_batch! :)

avatar image Steferich Nov 09 '18 at 01:07 PM

bump bump bump

(comments are locked)
10|2000 characters needed characters left
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question