Adding vehicles to Shootergame with custom gravity

I’m running a custom gravity mod based on 4.10 that overrides CharacterMovementComponent. I’ve built ShooterGame on top of that and am running around now quite nicely with custom gravity.

I’m having troubles implementing vehicles. I’ve got my own AVehicle class that inherits from APawn and a UVehicleMovementComponent that inherits from UCharacterMovementComponent. The reason I inherited from there is that the gravity code is in there. I’ve not actually changed anything in the movement component. It’s “as is”.

Currently I’ve managed to possess the vehicle, attach my character to it and that’s it. I can also unpossess it and the same instance of character jumps out (with health, ammo and all). But I can’t make the vehicle move. The vehicle gets the movement component in its constructor with objectinitializer. I’ve bound input to move forward axis. When I possess the vehicle with a controller, I set the movement mode to MOVE_Flying for the VehicleMovementComponent so that I can move it without checking surfaces or whatnot (it’s gonna be a rocket pod anyway), but the ■■■■■■ just sits still. I’ve debugged that it calls my MoveForward() function after I mount it (but it actually calls it every tick even when there is no input - is this a feature?). I’ve tried everything: AddForce, Velocity += 100, AddMovementInput etc. Nothing works. It won’t budge. Currently it looks like a standard copy-paste:


void AVehicle::MoveForward(float Val)
{
const FRotator Rotation = GetActorRotation();
const FVector Direction = FRotationMatrix(Rotation).GetScaledAxis(EAxis::X);
AddMovementInput(Direction, Val);
}

I’ve got the SkeletalMesh set to physics enabled (it’s just the SkeletalCube from the engine folders with a socket where the character gets stuck into) in c++ and double checked in the editor. I’ve been keeping the vehicle as simple as possible, so it has only a skeletalmesh and a movement component.

I’m suspecting the problem is not my MoveForward function at all, but somewhere else. I haven’t made any vehicles before, so I might be missing something really obvious.

Hey Groatse-

Rather than using the CharacterMovementComponent you may want to use a WheeledVehicleMovementComponent. You will have to copy over any code specific to your custom gravity settings however the vehicle component should already be setup to accept input for a vehicle.

Cheers

But would it actually help me, since my vehicle is not wheeled? I mean from what I can see in the WheeledVehicleMovementComponent, the whole concept is based on adding torque to a rotating component that delivers movement via physics, but that’s not at all what my vehicle is doing (it’s a rocket pack) so I would have to rewrite the whole thing.

Currently I’m thinking of rewriting my vehicle class to inherit from ACharacter instead of APawn, but it’s a pain in the [redacted] I’m not wanting to do yet. Not before I get this [redacted] cube moving at least.

I’ve made a little progress and found out that the movement goes through setting UpdatedComponent, which I’ve done now, but this doesn’t help me one bit yet.

The search continues…

Hi ,

I thought I wrote you a reply, but it got lost in the world of bits it seems.

Anyway. I don’t think the suggestion you put forth is very feasible. Since my vehicle doesn’t have wheels, and at least at a glance, the wheeledvehicle seems to be designed to produce torque to wheels on controller input. It then calculates separately the movement for each wheel. I don’t need any of this.

I’m doing a 6DOF rocket pack, and I’d essentially not have to just copy the custom gravity, but also redo most functions in the WheeledVehicleMovementComponent. While on the other hand the CharacterMovementComponent’s flying mode is perfect for me, as I can make it check on my custom gravity that is already being applied on the character. Well, it would be perfect, but my vehicle isn’t moving…

How exactly is your rocket vehicle going to behave? Is it a pod or something that the character actually gets into or is it a pack that the character wears? If it’s the latter then it would be easier to have the character check if the pack is attached/equipped and behave accordingly. If you are using the former then I would need to know more about how your vehicle is currently setup.

Well, I was going to make a base class for all my space ships and rocket pods to inherit from - they all would have had the same basic functionality: 6DOF, thruster controlled movement and weapons of various kind. The character mesh was to be attached to the vehicle mesh so the character was still shootable (ie. snipe a pilot from cockpit type of fun) and the vehicle itself had their own hitpoints - loss of which would cause an explosion. I have most of the framework in place - nothing happens when the vehicle runs out of hitpoints and weapons are not yet functional, but the framework is there - I haven’t implemented all the features yet because I got stuck abruptly with the movement.

So the short answer would be a pod - but the character is visible in it. The reason I didn’t go to the route of attach mesh and set to flying mode for the character was because I was trying to think ahead for other vehicles in this same category. At the moment we are not planning on making surface vehicles.

I’ve recently put in collision capsules and tried using them as the UpdatedComponent instead of my mesh (as I did originally just to test out the movement), but no movement ensued. Is there something specific I need to do for my class that inherits from APawn before regular movement with CharacterMovementComponent can ensue? I have manually inputed the UpdatedComponent, I’ve also tried the UpdatedPrimitive, but they don’t seem to be linked to my problems.

Do you have a SetupPlayerInputComponent() function in your vehicle class? Can you post the code for your base vehicle class and/or provide the project for me to test directly?

I’ll put the Vehicle.cpp here for now for the bits that would be interesting and left only the stuff relevant to movement.

I’ve taken out all the includes, replication code, BeginPlay() and Tick() from this post, because of the limit on characters.

This markup syntax is killing me…

  AVehicle::AVehicle(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{	

SNIP SNIP Constructor creates mesh, collisioncapsule and movement component, these might be of interest:

    RootComponent = CapsuleComponent;
	VehicleMovement->UpdatedComponent = RootComponent;
	VehicleMovement->DefaultLandMovementMode = MOVE_Flying;
}
void AVehicle::SetupPlayerInputComponent(class UInputComponent* InputComponent)
{
	Super::SetupPlayerInputComponent(InputComponent);
	InputComponent->BindAxis("MoveForward", this, &AVehicle::MoveForward);
	InputComponent->BindAxis("MoveUp", this, &AVehicle::MoveUp);
	InputComponent->BindAction("PossessVehicle", IE_Pressed, this, &AVehicle::ExitCharacter);
}
void AVehicle::MoveUp(float Val)
{
	if (Val != 0.f)
	{
		AddMovementInput(FVector::UpVector, Val);
	}
}
void AVehicle::MoveForward(float Val)
{
	const FRotator Rotation = GetActorRotation();
	const FVector Direction = FRotationMatrix(Rotation).GetScaledAxis(EAxis::X);
	AddMovementInput(Direction, Val);
	/*GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Blue, TEXT("Moving forward"));*/
}
void AVehicle::EnterCharacter(AShooterCharacter * Character)
{
	
	if (GetNetMode() == NM_Client)
	{
		ServerEnterVehicle(Character);
		return;
	}
	if (CharInVehicle != NULL)
	{
		return;
	}
	
	if (Character)
	{
		CharInVehicle = Character;
		Character->GetCharacterMovement()->StopMovementImmediately();
		Character->SetActorEnableCollision(false);
		Character->AttachRootComponentTo(VehicleMesh, CharacterSocket, EAttachLocation::SnapToTarget);		
	}

	if (Character->Controller)
	{
    	Character->Controller->Possess(this);	
	}	
}

Hey Groatse-

After stepping through the code I noticed that AddMovementInput() (AMI) makes a call to GetMovementComponent. The interesting thing is that when AMI is called inside a character class it eventually calls ACharacter::GetMovementComponent() whereas if AMI is called from a pawn class it instead calls APawn::GetMovementComponent. Rather than basing your vehicle class on Pawn, another option would be to base the vehicle class on Character and include a Child Actor component and some kind of triggering volume (sphere, box, etc.). When the player overlaps the trigger volume you set the child actor component to the Player to attach them to the vehicle. Hopefully this helps get the vehicle moving with the player properly.

Cheers

Thanks !

I was just wondering this exact same thing and did some preliminary testing with it and this is the way to go. Now rebasing my class off of ACharacter and it seems that everything works and I can crack on with the show.

Just a quick comment here, if you know a fast answer . I’m having trouble implementing Rotation change. For some reason my rotation on Pitch and Roll is locked out. I can do AddMovementInput and do AddActorlocalRotation for Yaw, but the other two axis are not working. Adding a whole bunch of rotation just pops the character there but then it jumps back again in the next tick. I’ve replicated the movement, but it still doesn’t work. It seems like something is keeping the capsule component straight, but I can’t locate the problem. Any ideas?

It was the gravity code doing that, it forces the capsule z-axis opposite the gravity direction. Needed for walking on surfaces to get the character head pointing up, but not for the rocket pods and space ships. Ok, solved again and back to the drawing board.