Learning Outcome - Creating Spherical Gravity and Understanding Spline Component
About the Project :
I implemented spherical gravity by adding Physical velocity to Player at each frames.
I also created Launch Star system simialr to Original game using Unreal Engine's built-in Spline Component.
Unreal Engine's 3rd Person Example Project's default animations were not working because of Spherical Gravity System I have added to Characer. Therefore, I had to change animation blueprints that can work well with character animation and my gravity system.
Future Update - Enemies and Camera like Original Game
Code Snippets are below.
PlayerPawn Class :
void AMarioGalaxyPawn::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
//return if player is not in normal state
if (CurrentState != EPlayerState::NORMAL)
return;
else
{
//Rotation from current location to Planet's center
FRotator NewRotation = UKismetMathLibrary::FindLookAtRotation(CurrentPlanet->GetActorLocation(), GetActorLocation());
SetActorRotation(UKismetMathLibrary::MakeRotFromZX(UKismetMathLibrary::GetForwardVector(NewRotation), GetActorForwardVector()));
//Applying Physics velocity to Player
CharacterCollision->SetPhysicsLinearVelocity(UKismetMathLibrary::GetForwardVector(NewRotation) * GravityForce, true);
//Setting Input vector for turning Player mesh and animation
InputVector = FVector(ForwardInputValue, RightInputValue, 0.0f);
//if input vector is 0, then return, else rotate player mesh
if (InputVector.Size() == 0.0f)
return;
FRotator NewInputRotation(0.0f, FollowCamera->GetRelativeRotation().Yaw + (InputVector.Rotation().Yaw - 90.0f), 0.0f);
CharacterMesh->SetRelativeRotation(NewInputRotation);
//Clamp Physical Velocity for running around in same speed for all direction
FVector CurrentVelocity = CharacterCollision->GetPhysicsLinearVelocity().GetClampedToSize(MinimumVelocity, MaximumVelocity);
//GEngine->AddOnScreenDebugMessage(-1, 1.f, FColor::Orange, FString::Printf(TEXT("%f"), CurrentVelocity.Size()));
CharacterCollision->SetPhysicsLinearVelocity(CurrentVelocity);
}
}
void AMarioGalaxyPawn::MoveForward(float Value)
{
if (CurrentState != EPlayerState::NORMAL)
return;
/*FRotator NewRotation(0.0f, FollowCamera->GetRelativeRotation().Yaw + (-90.0f * Value), 0.0f);
CharacterMesh->SetRelativeRotation(NewRotation);*/
//setting input value for input vector
ForwardInputValue = Value;
//adding physical velocity for forward movement
FVector Move = CharacterCollision->GetForwardVector() * Value * Acceleration;
CharacterCollision->SetPhysicsLinearVelocity(Move, true);
//CharacterCollision->GetPhysicsLinearVelocity();
//GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Orange, FString::Printf(TEXT("%s"), *CharacterCollision->GetPhysicsLinearVelocity().ToString()));
}
void AMarioGalaxyPawn::MoveRight(float Value)
{
if (CurrentState != EPlayerState::NORMAL)
return;
/*FRotator NewRotation(0.0f, FollowCamera->GetRelativeRotation().Yaw + (180.0f * Value), 0.0f);
CharacterMesh->SetRelativeRotation(NewRotation);*/
//setting input value for input vector
RightInputValue = Value;
//adding physical velocity for right movement
FVector Move = CharacterCollision->GetRightVector() * Value * Acceleration;
CharacterCollision->SetPhysicsLinearVelocity(Move, true);
}
void AMarioGalaxyPawn::Jump()
{
if (!CanJump || CurrentState != EPlayerState::NORMAL)
return;
MaximumVelocity = 2000.0f;
//adding physical velocity for jump
FVector Move = CharacterCollision->GetUpVector() * JumpForce * Acceleration;
CharacterCollision->SetPhysicsLinearVelocity(Move, true);
}
Launch Star :
void ALaunchingStart::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
//when player touch the start, start moving player along spline
if (PlayerTarget != nullptr && bCanMoveActor)
{
//calculating time for getting distance of spline from starting point, based on time to complete spline path
float CurrentSplineTime = (GetWorld()->GetTimeSeconds() - StartTime) / TimeToCompletePath;
//getting current distance on spline from time
float Distance = SplinePath->GetSplineLength() * CurrentSplineTime;
//getting current position on spline from distance
FVector Position = SplinePath->GetLocationAtDistanceAlongSpline(Distance, ESplineCoordinateSpace::World);
//getting current direction on spline from distance
FVector Direction = SplinePath->GetDirectionAtDistanceAlongSpline(Distance, ESplineCoordinateSpace::Local);
//setting player position on spline
PlayerRootPoint->SetWorldLocation(Position);
//setting player forward vector in spline direction
FRotator NewRotator = UKismetMathLibrary::MakeRotFromX(Direction);
PlayerRootPoint->SetWorldRotation(NewRotator);
//Player about to reach end
if (CurrentSplineTime >= 0.90f && PlayerTarget->IsStartedRolling == false)
PlayerTarget->IsStartedRolling = true;
//Player reach the end
if (CurrentSplineTime >= 1.0f)
{
bCanMoveActor = false;
//dettach Player from scene component of star actor
PlayerTarget->RemoveFromRoot();
//this method will start applying physical velocity to player, for spherical gravity
PlayerTarget->EndOfSplineFollow();
}
}
}
//Player touch the star
void ALaunchingStart::OnStarBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
if ((OtherActor != nullptr) && (OtherActor != this) && (OtherComp != nullptr))
{
if (OtherActor != Cast(OtherActor))
return;
PlayerTarget = Cast(OtherActor);
PlayerTarget->AttachPlayerToStar();
//attach player to scene component of star actor, this "PlayerRootPoint" component will follow the spline path
FAttachmentTransformRules TransformRules = FAttachmentTransformRules(EAttachmentRule::SnapToTarget, EAttachmentRule::SnapToTarget, EAttachmentRule::KeepWorld, true);
PlayerTarget->AttachToComponent(PlayerRootPoint, TransformRules);
//GEngine->AddOnScreenDebugMessage(-1, 1.f, FColor::Orange, FString::Printf(TEXT("Collision Occured")));
//Pull back the player actor
//PullBack(); call launch() inside PullBack
LaunchPlayer();
}
}
void ALaunchingStart::LaunchPlayer()
{
//get time when player touch the star
StartTime = GetWorld()->GetTimeSeconds();
//this bool will trigger Tick to move player along spline
bCanMoveActor = true;
}