Skip to content

Commit

Permalink
Merge pull request #80 from dyanikoglu/dev
Browse files Browse the repository at this point in the history
Release v4.9
  • Loading branch information
dyanikoglu authored Oct 30, 2020
2 parents e643753 + e84506c commit 8ff783e
Show file tree
Hide file tree
Showing 17 changed files with 75 additions and 139 deletions.
2 changes: 1 addition & 1 deletion ALSV4_CPP.uplugin
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"FileVersion": 3,
"Version": 1,
"VersionName": "4.8",
"VersionName": "4.9",
"FriendlyName": "Advanced Locomotion System V4 on C++",
"Description": "Performance optimized C++ port of LongmireLocomotion's Advanced Locomotion System V4",
"Category": "Animation",
Expand Down
Binary file modified Content/AdvancedLocomotionV4/Blueprints/UI/ALS_HUD.uasset
Binary file not shown.
Binary file not shown.
Binary file not shown.
48 changes: 14 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,53 +1,33 @@
# Advanced Locomotion System V4 on C++
![image](https://github.com/dyanikoglu/ALSV4_CPP/raw/main/Resources/Readme_Content_2.gif)

Performance optimized & replicated C++ port of [Advanced Locomotion System V4](https://www.unrealengine.com/marketplace/en-US/product/advanced-locomotion-system-v1) for **Unreal Engine 4.25** with additional bug fixes.
Replicated & optimized C++ port of [Advanced Locomotion System V4](https://www.unrealengine.com/marketplace/en-US/product/advanced-locomotion-system-v1) for **Unreal Engine 4.25** with additional bug fixes.

## Features
- Converted into plugin structure (by [AHGS-Jens](https://github.com/AHGS-Jens)). You can immediately start using it in your project without doing any serious change in your project configuration.
- Source code is highly optimized while being ported from blueprints. For 100 characters in a scene, CPU time is decreased from ~17ms to ~10ms.
- Currently, only Windows & Linux are supported, and tested.
- Network performance optimized, and comes with full replication support (Big kudos to [senfkorn92](https://github.com/senfkorn92) for his work). ALSV4_CPP currently beats ALS V3 and other BP based V4 replication implementations on network performance:
```
Advanced Locomotion System V3 (BP):
Total outgoing bandwidth is 686KB over 60 seconds (30 seconds playing server, 30 on client).
Character Actor Data sent over network - 43KB
'ReplicatedMovement' Data sent over network - 19KB
Highest RPC Data sent over network - 90KB
Overall Property Size - 46KB
Overall RPC Size - 201KB
## Supported Systems
- Windows 64-bit
- Linux

Advanced Locomotion System V4 (BP):
Total outgoing bandwidth is 2.7MB over 60 seconds (30 seconds playing server, 30 on client).
Character Actor Data sent over network - 116KB
'ReplicatedMovement' Data sent over network - 45KB
Highest RPC Data sent over network - 536KB
Overall Property Size - 209KB
Overall RPC Size - 1.7MB
*Mac, Android, IOS, and console builds are not tested and supported at the moment*

Advanced Locomotion System V4 (C++):
Total outgoing bandwidth is 618KB over 60 seconds (30 seconds playing server, 30 on client).
Character Actor Data sent over network - 38KB
'ReplicatedMovement' Data sent over network - 14KB
Highest RPC Data sent over network - 48KB
Overall Property Size - 41.1KB
Overall RPC Size - 91.1KB
## Features
- Full replication support with low bandwith usage
- Plugin structure
- Highly optimized for production
- Lots of bug fixes additional to marketplace version

Netprofiler benchmark by @Scragnog
```
## Known Issues
- See [Issues](https://github.com/dyanikoglu/ALSV4_CPP/issues) section

## Setting Up The Plugin
- Clone the repository inside your project's `Plugins` folder, or download the source code zip file for latest release and extract it into your project's `Plugins` folder.
- Clone the repository inside your project's `Plugins` folder, or download the latest release and extract it into your project's `Plugins` folder.
- Put `Config/DefaultInput.ini` from the plugin folder inside your project's config folder. If your project already have this .ini file, merge it into yours.
- Add the lines below into your `DefaultEngine.ini`, below `[/Script/Engine.CollisionProfile]` tag (Create the tag if it doesn't exist):
```
+Profiles=(Name="ALS_Character",CollisionEnabled=QueryAndPhysics,bCanModify=True,ObjectTypeName="Pawn",CustomResponses=((Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore),(Channel="Climbable",Response=ECR_Ignore)),HelpMessage="Custom collision settings for the capsule in the ALS_BaseCharacter.")
+DefaultChannelResponses=(Channel=ECC_GameTraceChannel2,DefaultResponse=ECR_Block,bTraceType=True,bStaticObject=False,Name="Climbable")
```
- Generate Visual Studio Project files, and compile your project. (Unreal Engine 4.25.2 & 4.25.3 update broke compiling distribution binaries for plugins, so you need to compile them yourself)
- Launch the project, and enable plugin content viewer as seen below. This will show contents of the ALS in your content browser:
- Launch the project, and enable plugin content viewer as seen below. This will show contents of the plugin in your content browser:
![image](https://github.com/dyanikoglu/ALSV4_CPP/raw/main/Resources/Readme_Content_1.png)
- If you're getting problems with the plugin binaries, try compiling them yourself from the source.

## License & Contribution
**Source code** of the plugin is licensed under MIT license, and other developers are encouraged to fork the repository, open issues & pull requests to help the development.
41 changes: 28 additions & 13 deletions Source/ALSV4_CPP/Private/Character/ALSBaseCharacter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
#include "Kismet/KismetMathLibrary.h"
#include "Kismet/GameplayStatics.h"
#include "TimerManager.h"
#include "Logging/TokenizedMessage.h"
#include "Net/UnrealNetwork.h"

AALSBaseCharacter::AALSBaseCharacter(const FObjectInitializer& ObjectInitializer)
Expand Down Expand Up @@ -107,6 +106,9 @@ void AALSBaseCharacter::BeginPlay()
{
Super::BeginPlay();

// If we're in networked game, disable curved movement
bDisableCurvedMovement = !IsNetMode(ENetMode::NM_Standalone);

FOnTimelineFloat TimelineUpdated;
FOnTimelineEvent TimelineFinished;
TimelineUpdated.BindUFunction(this, FName(TEXT("MantleUpdate")));
Expand Down Expand Up @@ -963,7 +965,7 @@ void AALSBaseCharacter::SetEssentialValues(float DeltaTime)

// Determine if the character has movement input by getting its movement input amount.
// The Movement Input Amount is equal to the current acceleration divided by the max acceleration so that
// it has a range of 0-1, 1 being the maximum possible amount of input, and 0 beiung none.
// it has a range of 0-1, 1 being the maximum possible amount of input, and 0 being none.
// If the character has movement input, update the Last Movement Input Rotation.
SetMovementInputAmount(ReplicatedCurrentAcceleration.Size() / EasedMaxAcceleration);
SetHasMovementInput(MovementInputAmount > 0.0f);
Expand Down Expand Up @@ -991,10 +993,19 @@ void AALSBaseCharacter::UpdateCharacterMovement()
}

// Use the allowed gait to update the movement settings.
UpdateDynamicMovementSettings(AllowedGait);
if (bDisableCurvedMovement)
{
// Don't use curves for movement
UpdateDynamicMovementSettingsNetworked(AllowedGait);
}
else
{
// Use curves for movement
UpdateDynamicMovementSettingsStandalone(AllowedGait);
}
}

void AALSBaseCharacter::UpdateDynamicMovementSettings(EALSGait AllowedGait)
void AALSBaseCharacter::UpdateDynamicMovementSettingsStandalone(EALSGait AllowedGait)
{
// Get the Current Movement Settings.
CurrentMovementSettings = GetTargetMovementSettings();
Expand All @@ -1005,26 +1016,30 @@ void AALSBaseCharacter::UpdateDynamicMovementSettings(EALSGait AllowedGait)
const float MappedSpeed = GetMappedSpeed();
const FVector CurveVec = CurrentMovementSettings.MovementCurve->GetVectorValue(MappedSpeed);

// Update the Character Max Walk Speed to the configured speeds based on the currently Allowed Gait.
GetCharacterMovement()->MaxWalkSpeed = NewMaxSpeed;
GetCharacterMovement()->MaxAcceleration = CurveVec.X;
GetCharacterMovement()->BrakingDecelerationWalking = CurveVec.Y;
GetCharacterMovement()->GroundFriction = CurveVec.Z;
}

void AALSBaseCharacter::UpdateDynamicMovementSettingsNetworked(EALSGait AllowedGait)
{
// Get the Current Movement Settings.
CurrentMovementSettings = GetTargetMovementSettings();
float NewMaxSpeed = CurrentMovementSettings.GetSpeedForGait(AllowedGait);

// Update the Character Max Walk Speed to the configured speeds based on the currently Allowed Gait.
if (IsLocallyControlled() || HasAuthority())
{
if (GetCharacterMovement()->MaxWalkSpeed != NewMaxSpeed)
{
MyCharacterMovementComponent->SetMaxWalkingSpeed(NewMaxSpeed);
}
if (GetCharacterMovement()->MaxAcceleration != CurveVec.X
|| GetCharacterMovement()->BrakingDecelerationWalking != CurveVec.Y
|| GetCharacterMovement()->GroundFriction != CurveVec.Z)
{
MyCharacterMovementComponent->SetMovementSettings(CurveVec);
}
}
else
{
GetCharacterMovement()->MaxWalkSpeed = NewMaxSpeed;
GetCharacterMovement()->MaxAcceleration = CurveVec.X;
GetCharacterMovement()->BrakingDecelerationWalking = CurveVec.Y;
GetCharacterMovement()->GroundFriction = CurveVec.Z;
}
}

Expand Down
2 changes: 1 addition & 1 deletion Source/ALSV4_CPP/Private/Character/ALSCharacter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ ECollisionChannel AALSCharacter::GetThirdPersonTraceParams(FVector& TraceOrigin,
FTransform AALSCharacter::GetThirdPersonPivotTarget()
{
return FTransform(GetActorRotation(),
(GetMesh()->GetSocketLocation(TEXT("Head")) + GetMesh()->GetSocketLocation(TEXT("Root"))) / 2.0f,
(GetMesh()->GetSocketLocation(TEXT("Head")) + GetMesh()->GetSocketLocation(TEXT("root"))) / 2.0f,
FVector::OneVector);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Project: Advanced Locomotion System V4 on C++
// Source Code: https://github.com/dyanikoglu/ALSV4_CPP
// Original Author: Haziq Fadhil
// Contributors:
// Contributors: Doga Can Yanikoglu


#include "Character/ALSCharacterMovementComponent.h"
Expand All @@ -26,14 +26,6 @@ void UALSCharacterMovementComponent::OnMovementUpdated(float DeltaTime, const FV
{
MaxWalkSpeed = MyNewMaxWalkSpeed;
MaxWalkSpeedCrouched = MyNewMaxWalkSpeed;
MaxAcceleration = MyNewMaxAcceleration;
BrakingDecelerationWalking = MyNewBraking;
GroundFriction = MyNewGroundFriction;

// Ensures server Movement Settings values updates to latest
bRequestMovementSettingsChange = MaxAcceleration != RealMaxAcceleration
|| BrakingDecelerationWalking != RealBraking
|| GroundFriction != RealGroundFriction;
}
}

Expand All @@ -46,7 +38,7 @@ void UALSCharacterMovementComponent::UpdateFromCompressedFlags(uint8 Flags) // C

class FNetworkPredictionData_Client* UALSCharacterMovementComponent::GetPredictionData_Client() const
{
check(PawnOwner != NULL);
check(PawnOwner != nullptr);

if (!ClientPredictionData)
{
Expand Down Expand Up @@ -82,7 +74,7 @@ uint8 UALSCharacterMovementComponent::FSavedMove_My::GetCompressedFlags() const
bool UALSCharacterMovementComponent::FSavedMove_My::CanCombineWith(const FSavedMovePtr& NewMove, ACharacter* Character,
float MaxDelta) const
{
// Set which moves can be combined together. This will depend on the bit flags that are used.
// Set which moves can be combined together. This will depend on the bit flags that are used.
if (bSavedRequestMovementSettingsChange != ((FSavedMove_My*)&NewMove)->bSavedRequestMovementSettingsChange)
{
return false;
Expand All @@ -103,13 +95,6 @@ void UALSCharacterMovementComponent::FSavedMove_My::SetMoveFor(ACharacter* Chara
}
}

void UALSCharacterMovementComponent::FSavedMove_My::PrepMoveFor(class ACharacter* Character)
{
Super::PrepMoveFor(Character);

UALSCharacterMovementComponent* CharacterMovement = Cast<UALSCharacterMovementComponent>(Character->GetCharacterMovement());
}

UALSCharacterMovementComponent::FNetworkPredictionData_Client_My::FNetworkPredictionData_Client_My(
const UCharacterMovementComponent& ClientMovement)
: Super(ClientMovement)
Expand All @@ -124,9 +109,7 @@ FSavedMovePtr UALSCharacterMovementComponent::FNetworkPredictionData_Client_My::
// Set Movement Settings RPC to transfer the current Movement Settings from the Owning Client to the Server
bool UALSCharacterMovementComponent::Server_SetMaxWalkingSpeed_Validate(const float NewMaxWalkSpeed)
{
if (NewMaxWalkSpeed < 0.f || NewMaxWalkSpeed > 2000.f)
return false;
return true;
return NewMaxWalkSpeed >= 0.f && NewMaxWalkSpeed <= 2000.f;
}

void UALSCharacterMovementComponent::Server_SetMaxWalkingSpeed_Implementation(const float NewMaxWalkSpeed)
Expand All @@ -143,34 +126,3 @@ void UALSCharacterMovementComponent::SetMaxWalkingSpeed(float NewMaxWalkSpeed)
}
bRequestMovementSettingsChange = true;
}

// Set Max Walking Speed RPC to transfer the current Max Walking Speed from the Owning Client to the Server
bool UALSCharacterMovementComponent::Server_SetMovementSettings_Validate(const FVector NewMovementSettings)
{
return true;
}

void UALSCharacterMovementComponent::Server_SetMovementSettings_Implementation(const FVector NewMovementSettings)
{
MyNewMaxAcceleration = NewMovementSettings.X;
MyNewBraking = NewMovementSettings.Y;
MyNewGroundFriction = NewMovementSettings.Z;
bRequestMovementSettingsChange = true;
}

void UALSCharacterMovementComponent::SetMovementSettings(FVector NewMovementSettings)
{
if (PawnOwner->IsLocallyControlled())
{
MyNewMaxAcceleration = NewMovementSettings.X;
MyNewBraking = NewMovementSettings.Y;
MyNewGroundFriction = NewMovementSettings.Z;
Server_SetMovementSettings(NewMovementSettings);
}
bRequestMovementSettingsChange = true;

// Save Server Movement Settings for comparison during movement update
RealMaxAcceleration = NewMovementSettings.X;
RealBraking = NewMovementSettings.Y;
RealGroundFriction = NewMovementSettings.Z;
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
#include "Character/ALSPlayerCameraManager.h"


#include "DrawDebugHelpers.h"
#include "Character/ALSBaseCharacter.h"
#include "Character/Animation/ALSPlayerCameraBehavior.h"
#include "Kismet/KismetMathLibrary.h"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,8 @@ void UALSCharacterAnimInstance::UpdateLayerValues()

void UALSCharacterAnimInstance::UpdateFootIK(float DeltaSeconds)
{
FVector FootOffsetLTarget;
FVector FootOffsetRTarget;
// Update Foot Locking values.
SetFootLocking(DeltaSeconds, FName(TEXT("Enable_FootIK_L")), FName(TEXT("FootLock_L")),
FName(TEXT("ik_foot_l")), FootIKValues.FootLock_L_Alpha, FootIKValues.UseFootLockCurve_L,
Expand All @@ -274,11 +276,11 @@ void UALSCharacterAnimInstance::UpdateFootIK(float DeltaSeconds)
else if (!MovementState.Ragdoll())
{
// Update all Foot Lock and Foot Offset values when not In Air
SetFootOffsets(DeltaSeconds, FName(TEXT("Enable_FootIK_L")), FName(TEXT("ik_foot_l")), FName(TEXT("Root")), FootOffsetLTargetCached,
SetFootOffsets(DeltaSeconds, FName(TEXT("Enable_FootIK_L")), FName(TEXT("ik_foot_l")), FName(TEXT("root")), FootOffsetLTarget,
FootIKValues.FootOffset_L_Location, FootIKValues.FootOffset_L_Rotation);
SetFootOffsets(DeltaSeconds, FName(TEXT("Enable_FootIK_R")), FName(TEXT("ik_foot_r")), FName(TEXT("Root")), FootOffsetRTargetCached,
SetFootOffsets(DeltaSeconds, FName(TEXT("Enable_FootIK_R")), FName(TEXT("ik_foot_r")), FName(TEXT("root")), FootOffsetRTarget,
FootIKValues.FootOffset_R_Location, FootIKValues.FootOffset_R_Rotation);
SetPelvisIKOffset(DeltaSeconds, FootOffsetLTargetCached, FootOffsetRTargetCached);
SetPelvisIKOffset(DeltaSeconds, FootOffsetLTarget, FootOffsetRTarget);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ void UALSNotifyStateOverlayOverride::NotifyEnd(USkeletalMeshComponent* MeshComp,
FString UALSNotifyStateOverlayOverride::GetNotifyName_Implementation() const
{
FString Name(TEXT("Overlay Override State: "));
Name.Append(GetEnumerationToString(static_cast<EALSOverlayState>(OverlayOverrideState)));
Name.Append(FString::FromInt(OverlayOverrideState));
return Name;
}
23 changes: 14 additions & 9 deletions Source/ALSV4_CPP/Public/Character/ALSBaseCharacter.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ class ALSV4_CPP_API AALSBaseCharacter : public ACharacter
UFUNCTION(BlueprintCallable, NetMulticast, Reliable, Category = "ALS|Character States")
void Multicast_MantleStart(float MantleHeight, const FALSComponentAndTransform& MantleLedgeWS, EALSMantleType MantleType);

/** Ragolling*/
/** Ragdolling*/
UFUNCTION(BlueprintCallable, Category = "ALS|Character States")
void ReplicatedRagdollStart();

Expand Down Expand Up @@ -333,7 +333,7 @@ class ALSV4_CPP_API AALSBaseCharacter : public ACharacter

void SetActorLocationDuringRagdoll(float DeltaTime);

/** Stace Changes */
/** State Changes */

virtual void OnMovementModeChanged(EMovementMode PrevMovementMode, uint8 PreviousCustomMode = 0) override;

Expand Down Expand Up @@ -365,7 +365,9 @@ class ALSV4_CPP_API AALSBaseCharacter : public ACharacter

void UpdateCharacterMovement();

void UpdateDynamicMovementSettings(EALSGait AllowedGait);
void UpdateDynamicMovementSettingsNetworked(EALSGait AllowedGait);

void UpdateDynamicMovementSettingsStandalone(EALSGait AllowedGait);

void UpdateGroundedRotation(float DeltaTime);

Expand Down Expand Up @@ -450,13 +452,13 @@ class ALSV4_CPP_API AALSBaseCharacter : public ACharacter

/** Input */

UPROPERTY(EditAnywhere, replicated, BlueprintReadWrite, Category = "ALS|Input")
UPROPERTY(EditAnywhere, Replicated, BlueprintReadWrite, Category = "ALS|Input")
EALSRotationMode DesiredRotationMode = EALSRotationMode::LookingDirection;

UPROPERTY(EditAnywhere, replicated, BlueprintReadWrite, Category = "ALS|Input")
UPROPERTY(EditAnywhere, Replicated, BlueprintReadWrite, Category = "ALS|Input")
EALSGait DesiredGait = EALSGait::Running;

UPROPERTY(EditAnywhere, BlueprintReadWrite, replicated, Category = "ALS|Input")
UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "ALS|Input")
EALSStance DesiredStance = EALSStance::Standing;

UPROPERTY(EditDefaultsOnly, Category = "ALS|Input", BlueprintReadOnly)
Expand Down Expand Up @@ -554,10 +556,10 @@ class ALSV4_CPP_API AALSBaseCharacter : public ACharacter
UPROPERTY(BlueprintReadOnly, Category = "ALS|Essential Information")
float EasedMaxAcceleration;

UPROPERTY(BlueprintReadOnly, replicated, Category = "ALS|Essential Information")
UPROPERTY(BlueprintReadOnly, Replicated, Category = "ALS|Essential Information")
FVector ReplicatedCurrentAcceleration;

UPROPERTY(BlueprintReadOnly, replicated, Category = "ALS|Essential Information")
UPROPERTY(BlueprintReadOnly, Replicated, Category = "ALS|Essential Information")
FRotator ReplicatedControlRotation;

/** State Values */
Expand Down Expand Up @@ -645,7 +647,7 @@ class ALSV4_CPP_API AALSBaseCharacter : public ACharacter
UPROPERTY(BlueprintReadOnly, Category = "ALS|Ragdoll System")
FVector LastRagdollVelocity;

UPROPERTY(BlueprintReadOnly, replicated, Category = "ALS|Ragdoll System")
UPROPERTY(BlueprintReadOnly, Replicated, Category = "ALS|Ragdoll System")
FVector TargetRagdollLocation;

/* Server ragdoll pull force storage*/
Expand Down Expand Up @@ -677,4 +679,7 @@ class ALSV4_CPP_API AALSBaseCharacter : public ACharacter

/* Smooth out aiming by interping control rotation*/
FRotator AimingRotation;

/** We won't use curve based movement on networked games */
bool bDisableCurvedMovement = false;
};
Loading

0 comments on commit 8ff783e

Please sign in to comment.