Hello fellow developers,
I have a bit of a problem in UE4. I am attempting to build a tank, I have spawned the chassis using blue prints.
ATestMode::ATestMode(const class FPostConstructInitializeProperties& PCIP)
: Super(PCIP)
{
// set default pawn class to our Blueprinted character
static ConstructorHelpers::FObjectFinder<UBlueprint> PlayerPawnObject(TEXT("Blueprint'/Game/Blueprints/TestTankChasis.TestTankChasis'"));
if (PlayerPawnObject.Object != NULL)
{
DefaultPawnClass = (UClass*)PlayerPawnObject.Object->GeneratedClass;
}
}
I was able to set up some code to get the chassis moving around and rotating.
Next I went to create a tank turret, I added the mesh to the chassis using blueprints, and after running it appeared ontop of the chassis moving and rotating with it.
Next I need to attach a boom and camera to the turret and have it rotating individually of the chassis. This is where I ran into problems.
Currently, the boom and camera are attached to the chassis, the objective is to have them be attached to the turret so the chassis can rotate individually of the turret and vice versa. ABaseTank is my chassis.
Header:
#pragma once
#include "GameFramework/Character.h"
#include "BaseTank.generated.h"
/**
*
*/
UCLASS()
class ABaseTank : public ACharacter
{
GENERATED_UCLASS_BODY()
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera)
TSubobjectPtr<class USpringArmComponent> CameraBoom;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera)
TSubobjectPtr<class UCameraComponent> FollowCamera;
virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) OVERRIDE;
UPROPERTY(EditDefaultsOnly, Category = "Tank Variables")
float ChassisTurnRate;
UFUNCTION()
void MoveForward(float Val);
UFUNCTION()
void RotateChassis(float Val);
};
Source:
ABaseTank::ABaseTank(const class FPostConstructInitializeProperties& PCIP)
: Super(PCIP)
{
// Create a camera boom (pulls in towards the player if there is a collision)
CameraBoom = PCIP.CreateDefaultSubobject<USpringArmComponent>(this, TEXT("CameraBoom"));
CameraBoom->AttachTo(RootComponent);
CameraBoom->TargetArmLength = 300.0f; // The camera follows at this distance behind the character
CameraBoom->bUseControllerViewRotation = true; // Rotate the arm based on the controller
// Create a follow camera
FollowCamera = PCIP.CreateDefaultSubobject<UCameraComponent>(this, TEXT("FollowCamera"));
FollowCamera->AttachTo(CameraBoom, USpringArmComponent::SocketName); // Attach the camera to the end of the boom and let the boom adjust to match the controller orientation
FollowCamera->bUseControllerViewRotation = false; // Camera does not rotate relative to arm
}
With movement and rotation split up into different functions.
Input:
void ABaseTank::SetupPlayerInputComponent(class UInputComponent* InputComponent)
{
check(InputComponent);
InputComponent->BindAxis("MoveForward", this, &ABaseTank::MoveForward);
InputComponent->BindAxis("Rotate", this, &ABaseTank::RotateChassis);
}
Movement:
void ABaseTank::MoveForward(float Value)
{
if ((Controller != NULL) && (Value != 0.0f))
{
// find out which way is forward
FRotator Rotation = Controller->GetControlRotation();
// Limit pitch when walking or falling
if (CharacterMovement->IsMovingOnGround() || CharacterMovement->IsFalling())
{
Rotation.Pitch = 0.0f;
}
// add movement in that direction
const FVector Direction = FRotationMatrix(Rotation).GetScaledAxis(EAxis::X);
AddMovementInput(Direction, Value);
}
}
Rotation:
void ABaseTank::RotateChassis(float Value)
{
if ((Controller != NULL) && (Value != 0.0f))
{
AddControllerYawInput(Value * ChassisTurnRate * GetWorld()->GetDeltaSeconds());
}
}
I added the code necessary to control the boom and camera with the mouse.
void ABaseTank::SetupPlayerInputComponent(class UInputComponent* InputComponent)
{
check(InputComponent);
//Keyboard chassis rotation
InputComponent->BindAxis("MoveForward", this, &ABaseTank::MoveForward);
InputComponent->BindAxis("Rotate", this, &ABaseTank::RotateChassis);
//Mouse chassis rotation
InputComponent->BindAxis("Turn", this, &ATankTurret::AddControllerYawInput);
InputComponent->BindAxis("LookUp", this, &ATankTurret::AddControllerPitchInput);
}
Next I created my TankTurret class.
I moved the code for creating the boom and camera and mouse rotation to the tank turret.
Header
#pragma once
#include "GameFramework/Pawn.h"
#include "TankTurret.generated.h"
/**
*
*/
UCLASS()
class ATankTurret : public APawn
{
GENERATED_UCLASS_BODY()
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera)
TSubobjectPtr<class USpringArmComponent> CameraBoom;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera)
TSubobjectPtr<class UCameraComponent> FollowCamera;
protected:
virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) OVERRIDE;
};
Source:
#include "../TankGame.h"
#include "TankTurret.h"
ATankTurret::ATankTurret(const class FPostConstructInitializeProperties& PCIP)
: Super(PCIP)
{
// Create a camera boom (pulls in towards the player if there is a collision)
CameraBoom = PCIP.CreateDefaultSubobject<USpringArmComponent>(this, TEXT("CameraBoom"));
CameraBoom->AttachTo(RootComponent);
CameraBoom->TargetArmLength = 300.0f; // The camera follows at this distance behind the character
CameraBoom->bUseControllerViewRotation = true; // Rotate the arm based on the controller
// Create a follow camera
FollowCamera = PCIP.CreateDefaultSubobject<UCameraComponent>(this, TEXT("FollowCamera"));
FollowCamera->AttachTo(CameraBoom, USpringArmComponent::SocketName); // Attach the camera to the end of the boom and let the boom adjust to match the controller orientation
FollowCamera->bUseControllerViewRotation = false; // Camera does not rotate relative to arm
}
void ATankTurret::SetupPlayerInputComponent(UInputComponent* InputComponent)
{
InputComponent->BindAxis("Turn", this, &ATankTurret::AddControllerYawInput);
InputComponent->BindAxis("LookUp", this, &ATankTurret::AddControllerPitchInput);
}
Now, the turret should be able to rotate separately from the chassis, however I do not understand how I need to spawn the turret in order for this code to be executed. Currently, the turret mesh is positioned ontop of the chassis as I attached it there using blueprints, but I can not get it to do anything individually from the chassis. How does UE4 associate classes and meshes together? The way I see it, the chassis and the turret need to be two different classes that effect two different meshes and have separate code from one another, how can I achieve this?
Any help would be greatly appreciated.