This, like the Use system tutorial, is a tutorial that i made in the UE4 beta forums, and now i put them here, so more people can enjoy them.
The code is now uploaded to github, feel free to grab it, instructions on how to add to a base ShooterGame example are there. GitHub - vblanco20-1/UnrealJetpack: Unreal Engine 4 Jetpack and Walljump code
The first thing ive done from a challenge, A jetpack system for the Shooter game. And ill explain how it works here and why it works that way. The system mimics a bit the way HALO reach jetpack worked. When you press the ebar key, it starts the jetpack and you fly up, when you release it, it stops and gravity gets you. The jetpack has fuel so you cant fly forever, and you need to take care of how much do you fly, Everything its configurable, so you can use it whatever you want, if you make the fuel time be 9999999, you have technically infinite flying time.
time, unlike my Use system, i release the original source files, as its implemented on ShooterGame demo, you just need to paste onto the SourceFolder of ShooterGame, and recompile to enjoy it.
The files that change are:
ShooterHUD.cpp: to add a number on the screen representing the percentage of the fuel you have, one is completely optional, you dont need to add it if oyu dont want the big number with the percentage.
JetpackCharacter.h and JetpackCharacter.cpp: to add the jetpack enable and disable logic, and to call Start and Stop jetpack functions, that enable or disable it.
JetpackMovementComponent.h and cpp: To add the actual logic for the modified movement when you are using the jetpack.
Code Explanation:
JetpackCharacter.h
// Somewhere public, property is the replicated property for the jetpack use, it will be send to so its syinced.
UPROPERTY(Transient, Replicated)
uint8 bIsUsingJetpack : 1;
// the start and stop functions are called when the user presses e or releases it, and handle if the jetpack shold fly or not
UFUNCTION(BlueprintCallable, Category=Jetpack)
virtual void StartJetpack();
UFUNCTION(BlueprintCallable, Category=Jetpack)
virtual void StopJetpack();
// Enable and Disable functions handle the "burnout" state of the jetpack, when you deplete the fuel, it needs some time to recover
virtual void DisableJetpack();
virtual void EnableJetpack();
// for the enable and disable. one is not replicated, as its not really needed, Enable and disable are client only functions, and handle imput mostly
bool bIsJetpackEnabled;
/** is the time in seconds the jetpack has to spend while its "burned" to be re enabled again */
UPROPERTY(Category="Character Movement", EditAnywhere, BlueprintReadWrite)
float JetpackRecovery;
// function is the one that allows the client to set the jetpack state in the server, so the variable is replicated
UFUNCTION(reliable, server)
virtual void ServerSetJetpack(bool bNewJetpack);
JetpackCharacter.cpp
// REPLICATION!! , function takes care of replicating every property that should be replicated
void AJetpackCharacter::GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
// except local owner: flag change is locally instigated
DOREPLIFETIME_CONDITION(AJetpackCharacter, bIsUsingJetpack, COND_SkipOwner);
}
//////////////////////////////////////////////////
// Start and Stop jetpack functions, you should add keybindings to them by blueprint or by config, the blueprint in the zip comes with that already set up in the E key
void AJetpackCharacter::StopJetpack()
{
if (Role < ROLE_Authority) // in a client
{
ServerSetJetpack(false); // call server to change variable
}
bIsUsingJetpack = false; // and then update the local version
}
void AJetpackCharacter::StartJetpack()
{
if(bIsJetpackEnabled) // check for if it is enabled, so you cant start flying again while the jetpack disabled due to the player depleting it
{
if (Role < ROLE_Authority) // we are in a client
{
ServerSetJetpack(true); // call server to change the variable
}
bIsUsingJetpack = true; // and then upate the local version
}
}
void AJetpackCharacter::ServerSetJetpack_Implementation(bool bNewJetpack)
{
// is the server version, so the bIsUsingJetpack variable is replicated properly across the network
bIsUsingJetpack = bNewJetpack;
}
////////////////////////////////////////////////////////
// Enable and Disable jetpack functions, for the "burnour" behaviour. Disable Jetpack is called from the movement component every time the jetpack runs out of fuel,
// and it sets a timer to re enable the jetpack again
void AJetpackCharacter::DisableJetpack()
{
// Debug Message
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("JetpackDisabled"));
bIsJetpackEnabled = false;
GetWorldTimerManager().SetTimer(this, &AShooterCharacter::EnableJetpack, JetpackRecovery, false);
}
void AJetpackCharacter::EnableJetpack()
{
// Debug Message
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Blue, TEXT("JetpackEnabled"));
bIsJetpackEnabled = true;
}
As you can see, the Character part mostly deals with imput and replication of the state of the jetpack, now comes the actual logic of it, in the Movement Component.
Movement Components are a part that is completeely new in UE4, in UE3, they didnt exist, the movement logic was done inside the actual and Controller. Now, it is in a separate component, wich you can swap if needed, and it has several useful properties.
JetpackMovementComponent.h: Here we add the declaration for several editable variables for the jetpack, and add functions
#pragma once
#include "JetpackCharacterMovement.generated.h"
UCLASS(HeaderGroup=Component)
class UJetpackCharacterMovement : public UShooterCharacterMovement
{
GENERATED_UCLASS_BODY()
/**Override the Perform Movement function so we can add the jetpack logic there */
virtual void PerformMovement(float DeltaTime) OVERRIDE;
/** Upwards Strength of the jetpack, the more it is, the bigger is the acceleration for the jetpack, if its too low, the gravity has more power and you dont even fly */
UPROPERTY(Category="Character Movement", EditAnywhere, BlueprintReadWrite)
float JetpackStrength ;
/** maximum fuel for the jetpack, goes in seconds, and its depleted with simple time, so if its 2, you can only fly for 2 seconds */
UPROPERTY(Category="Character Movement", EditAnywhere, BlueprintReadWrite)
float JetpackMaxFuel;
/** Multiplier for the jetpack fuel regeneration, uses the time, if its 0.5, and the JetpackMaxFuel is 2 seconds, that means that it will take 4 seconds to be back at 100% */
UPROPERTY(Category="Character Movement", EditAnywhere, BlueprintReadWrite)
float JetpackRefuelRate;
/** Holds the current fuel amount */
float Jetpackfuel;
};
JetpackCharacterMovement.cpp, the implementation of it.
It sees if the owner character has bIsUsingJetpack to true, and if its true, it applies the upwars force and uses some fuel, if the player is not using the jetpack, the code regenerates the fuel.
After all that, it just calls CharacterMovement::PerformMovement, wich takes care of everything else.
Continues below, post is waaay too long