How can I make my pawn move?

I have created my custom character in C++ and have it spawning in the world as the default thing that your character is possessing. It has my custom components attached, as in the code you read below you will see the debug lines show up so I do know they are there. When I hit ‘W’ ‘A’ ‘S’ or ‘D’ (I have them set as the axis input in the project settings) it will fire off my custom events shown in the code below. However, no movement is happening. I can’t make it move no matter how hard I’ve tried for the past 7 hours, and scouring the net (long work day, maybe my brain is fried.) I’ve tried SetPhysicsLinearVelocity, AddImpulse, etc. The debug line directly after the movement code works just fine, just… no movement. Any suggestions?

TheCharacter.h

#pragma once

#include "GameFramework/Character.h"
#include "TheCharacter.generated.h"

UCLASS()
class ATheCharacter : public APawn
{
	GENERATED_UCLASS_BODY()

	virtual void BeginPlay() OVERRIDE;
	virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) OVERRIDE;

	//Movement
	UFUNCTION() void MoveForward(float Val);		//handles moving forward and backwards
	UFUNCTION() void MoveRight(float Val);		//handles moving right and left

	TSubobjectPtr<UCameraComponent> myCamera;
	TSubobjectPtr<UStaticMeshComponent> myStaticMesh;
}

TheCharacter.cpp

#include "TEST_fps.h"
#include "TheCharacter.h"

ATheCharacter::ATheCharacter(const class FPostConstructInitializeProperties& PCIP) : Super(PCIP)
{
	myCamera = PCIP.CreateDefaultSubobject<UCameraComponent>(this, TEXT("myCamera"));
	myStaticMesh = PCIP.CreateDefaultSubobject<UStaticMeshComponent>(this, TEXT("myStaticMesh"));
	RootComponent = myStaticMesh;
	myCamera->AttachTo(RootComponent);

	static ConstructorHelpers::FObjectFinder<UStaticMesh> StaticMeshObj(TEXT("StaticMesh'/Game/Assets/MyStuff/Geometry/laser100.laser100'"));
	myStaticMesh->StaticMesh = StaticMeshObj.Object;
}

void ATheCharacter::BeginPlay()
{
	Super::BeginPlay();

	if (GEngine)
	{
		//Debug line shows up
		GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Blue, TEXT("TheCharacter: LOADED OK"));

		TArray<USceneComponent*, FDefaultAllocator> complist;
		RootComponent->GetChildrenComponents(true, complist);

		for (int i = 0; i < complist.Num(); i++)
		{
			//Debug line shows up
			GEngine->AddOnScreenDebugMessage(0-i, 4.f, FColor::Yellow, complist[i]->GetName());
		}
	}
}

void ATheCharacter::SetupPlayerInputComponent(UInputComponent* InputComponent)
{
	InputComponent->BindAxis("MoveForward", this, &ATheCharacter::MoveForward);
	InputComponent->BindAxis("MoveRight", this, &ATheCharacter::MoveRight); 
}

void ATheCharacter::MoveForward(float Val)
{
	if ((Controller != NULL) && (Val != 0.0f))
	{
		Cast<UStaticMeshComponent>(RootComponent)->SetPhysicsLinearVelocity(FVector(100.f, 0.0f, 0.0f));

		//Debug line shows up
		GEngine->AddOnScreenDebugMessage(-5, 1.f, FColor::Yellow, "MOVEFORWARD: SET PHYSICS LINEAR VELOCITY CALLED");
	}
}

void ATheCharacter::MoveRight(float Val)
{

	if ((Controller != NULL) && (Val != 0.0f))
	{
		Cast<UStaticMeshComponent>(RootComponent)->SetPhysicsLinearVelocity(FVector(0.0f, 100.0f, 0.0f));

		//Debug line shows up
		GEngine->AddOnScreenDebugMessage(-5, 1.f, FColor::Yellow, "MOVERIGHT: SET PHYSICS LINEAR VELOCITY CALLED");
	}
}

If someone could shed some light on this, I’d really appreciate it. I personally prefer to do all my work through code and C++, so, learning the syntax and how things need to happen in their specific ways with UE4 is a little bit frustrating at times.

Thanks so much guys, and if there is any additional information you need, please just ask and I will provide anything and everything.

If you’re using a character, do you not want to be using the movement component? Otherwise you could probably use a pawn and try applying physics velocity (note that your root component would need to be a primitive component with physics enabled to be pushed around by physics forces).

@Ambershee I am using a pawn, not a character. I wanted a fully stripped down version I could customize from scratch. :slight_smile: I’ve tried several things so far, including settings physics velocity and adding impulses and forces but it seems to be stubborn. The root component is the static mesh that all the physics and movement code is going into. I may get it solved yet, I will keep you updated!

You need to attach a movement component. Try adding something like this to your constructor:

// Create movement component
MovementComponent = PCIP.CreateDefaultSubobject<UFloatingPawnMovement>(this, TEXT("Movement"));
MovementComponent->UpdatedComponent = /* Insert your root component here */;

If you’re still stumped, I suggest looking at the DefaultPawn.cpp and using it as a starting point for your custom pawn class. Its a very simple extension of Pawn.

1 Like

Hi, @Clapfoot. I tried your suggestion actually myself another way, and your way, but both ways kind of still stumped me. Currently what I’m doing as a workaround is just keeping my root component as the static mesh with it’s model I put on it, and doing addimpulse/setphysicsXvelocity functions on it in order to make the pawn move. It’s moving, but, it’s not actually being ‘controlled’ yet, so I still feel I haven’t found a solution. But I’m still digging!

Did you try using AddMovementInput in your input delegate?

For example:

void APlayerShip::MoveRight(float Value)
{
    // add movement in that direction
    if (Value != 0.0f)
        AddMovementInput(FVector(0.0f, -1.0f, 0.0f), Value);
}

@Clapfoot. Aye, sir, I did. I’m mainly however focusing on getting an impulse based physics setup, so I’m thinking I may have to focus on just adding impulses directly to the StaticMesh that is my root. I’m interested in the actual impulses coming from player control though, such as AddMovementImput, just not that actual function.

@Clapfoot Although your solution didn’t solve my problem, I feel good about the help you’ve given me, and I want to give you a as the correct answer, but, I’m not sure about the rules on things like that here.

Don’t worry about marking the answer as correct since it didn’t actually solve the problem :). Good luck!

@Mindfane Physics simulation is true, currently, it was the first thing I checked, but good catch!

Maybe you need to set Simulate Physics to True ? I think I saw such an option under Physics/Collision section when you create a character using Blueprints.

I’m gonna keep banging at it (I work an an industrial garage as a machinist and mechanic so, this is all spare time for me), but when I do get it figured out, or if someone figures it out fully, I’ll definitely answer or it here!

Hi there, were you able to figure out a solution for this, as I am having the exact same issue while trying to do all in C++.

SetupPlayerInputComponent does NOT get called IF I drag the Character’s BP to viewport and run.

SetupPlayerInputComponent does NOT get called IF I use the SpawnActor() method in C++

SetupPlayerInputComponent call DOES work IF I assign the Character to DefaultPawnClass in GameMode constructor. But I don’t want to do that. I want to be able to spawn a Character and move it around without having to assign it as a default pawn.

OK, I found a solution that solved my issue. Not sure if it is the right one, but at least it works.

  • Get a reference to PlayerController
  • And have it possess the Character
  • This triggers the SetupPlayerInputComponent call of the Character’s class.

Example:

GetWorld()->GetFirstPlayerController()->Possess(myCharacter);

Hi

I have the same problem here, did you find a cleaner solution ?

thx

It looks like what you’re doing should work.

It’s possible that your player’s actor is not the instance you’re working on, so it doesn’t appear to be moving, but another instance is actually moving?

Try something like:

// Static function
ATheCharacter *ATheCharacter::GetPlayerPawn(APlayerController *player) {
  APawn *rtn = player->GetCharacter();
  if (!rtn)
    rtn = player->GetPawn();
  return Cast<ATheCharacter>(rtn);
}

void ATheCharacter::MoveRight() {
  this->K2_GetRootComponent()->SetPhysicsLinearVelocity(FVector(5000.f, 0.0f, 0.0f));
}

// On the player controller
void MyPlayerController::MoveRight() {
  auto pawn = ATheCharacter::GetPlayerPawn(this);
  if (pawn)
    pawn->MoveRight();
}

NB. Also, try use very high values for forces and impluses (5000, not 100); if you use a low value, you usually can’t see it in the editor due to friction, etc. on physics simulated objects.

below the page .there are 6 step.reading it may help you a lot !!