Hello, Im following the FPSTutorial Unreal have but instead of makeing it first person I wanted to make it third person.
I´ve come to the part where im putting in the projectiles but the tutorial binds them to the camera which looks really wierd for me since i want them to spawn from around my characters hands somewhere, not around one of his shoulders.
As it is now the spawn point also jumps between the right and left sholder depending on how Im looking around.
I think the solution to this would be to bind the spawning to the capsule component on my character instead, or maybe even straight to the mesh of my character.
Saddly though I have no clue how to do this, what parts of the code I should remove or replace. (So far I only understand about 50% of it all.)
I would really love it if someone could help me figure this out and explain to me a good way to make what I want happen, mostly so I don´t remove something important by mistake.
NEW:
I changed the muzzle to go from my skeletal mesh instead but Im still getting the problems with the projectile spawning location depending on which way im turning,
If I look forward it´s allright.
If I turn right.
If I turn left.
Can someone please help me figure out why this is happening.
FPSCharacter.cpp
#include "FPSCharacter.h"
#include "FPSProjectile.h"
#include "Components/CapsuleComponent.h"
// Sets default values
AFPSCharacter::AFPSCharacter()
{
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
CameraArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraSpringArm"));
CameraArm->SetupAttachment(GetCapsuleComponent());
CameraArm->TargetArmLength = 250.0f;
/* Set up character camera.*/
CharacterCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("CharacterCamera"));
CharacterCamera->SetupAttachment(CameraArm);
CharacterCamera->bUsePawnControlRotation = true;
}
// Called when the game starts or when spawned
void AFPSCharacter::BeginPlay()
{
Super::BeginPlay();
if (GEngine)
{
/* Put up a debug message for five seconds.*/
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("We are using FPSCharacter."));
}
}
// Called every frame
void AFPSCharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
// Called to bind functionality to input
void AFPSCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
/* Set up movement bindings.*/
PlayerInputComponent->BindAxis("MoveForward", this, &AFPSCharacter::MoveForward);
PlayerInputComponent->BindAxis("MoveRight", this, &AFPSCharacter::MoveRight);
/* Set up look bindings.*/
PlayerInputComponent->BindAxis("Turn", this, &AFPSCharacter::AddControllerYawInput);
PlayerInputComponent->BindAxis("LookUp", this, &AFPSCharacter::AddControllerPitchInput);
/* Set up jumping bindings.*/
PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &AFPSCharacter::StartJump);
PlayerInputComponent->BindAction("Jump", IE_Released, this, &AFPSCharacter::StopJump);
/* Set up fire binding.*/
PlayerInputComponent->BindAction("Fire", IE_Pressed, this, &AFPSCharacter::Fire);
}
void AFPSCharacter::MoveForward(float Value)
{
/* Find out which way is forward and record that the player wants to move that way.*/
FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::X);
AddMovementInput(Direction, Value);
}
void AFPSCharacter::MoveRight(float Value)
{
/* Find out which way is right and record that the player wants to move that way.*/
FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::Y);
AddMovementInput(Direction, Value);
}
void AFPSCharacter::StartJump()
{
bPressedJump = true;
}
void AFPSCharacter::StopJump()
{
bPressedJump = false;
}
void AFPSCharacter::Fire()
{
/* Attempt to fire a projectile.*/
if (ProjectileClass)
{
/* Get the skeletal mesh transform.*/
FVector SkeletalMeshComponentLocation;
FRotator SkeletalMeshComponentRotation;
GetActorEyesViewPoint(SkeletalMeshComponentLocation, SkeletalMeshComponentRotation);
/* Transform muzzle offset from camera space to world space.*/
FVector MuzzleLocation = SkeletalMeshComponentLocation + FTransform(SkeletalMeshComponentLocation).TransformVector(MuzzleOffset);
FRotator MuzzleRotation = SkeletalMeshComponentRotation;
/* Skew the aim slightly upwards.*/
MuzzleRotation.Pitch += 10.0f;
UWorld* World = GetWorld();
if (World)
{
FActorSpawnParameters SpawnParams;
SpawnParams.Owner = this;
SpawnParams.Instigator = Instigator;
/* Spawn projectile at muzzle.*/
AFPSProjectile* Projectile = World->SpawnActor<AFPSProjectile>(ProjectileClass, MuzzleLocation, MuzzleRotation, SpawnParams);
if (Projectile)
{
/* Set projectile´s initial trajectory.*/
FVector LaunchDirection = MuzzleRotation.Vector();
Projectile->FireInDirection(LaunchDirection);
}
}
}
}
FPSCharacter.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "Camera/CameraComponent.h"
#include "GameFramework\SpringArmComponent.h"
#include "FPSCharacter.generated.h"
UCLASS()
class FPSPROJECT_API AFPSCharacter : public ACharacter
{
GENERATED_BODY()
public:
// Sets default values for this character's properties
AFPSCharacter();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
/*Handles input for character movement.*/
UFUNCTION()
void MoveForward(float value);
UFUNCTION()
void MoveRight(float value);
UFUNCTION()
void StartJump();
UFUNCTION()
void StopJump();
UFUNCTION()
void Fire();
UPROPERTY(EditAnywhere, Category = "Components")
UCameraComponent* CharacterCamera;
UPROPERTY(EditAnywhere, Category = "Components")
USpringArmComponent* CameraArm;
/* Gun muzzle´s offset from camera location.*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay")
FVector MuzzleOffset;
/*Projectile class to spawn.*/
UPROPERTY(EditDefaultsOnly, Category = "Projectile")
TSubclassOf<class AFPSProjectile> ProjectileClass;
};