Starting multiplayer Marble game
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
using UnrealBuildTool;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class BigMarbleWorldTarget : TargetRules
|
||||
{
|
||||
public BigMarbleWorldTarget(TargetInfo Target) : base(Target)
|
||||
{
|
||||
Type = TargetType.Game;
|
||||
DefaultBuildSettings = BuildSettingsVersion.V7;
|
||||
IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_8;
|
||||
ExtraModuleNames.Add("BigMarbleWorld");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class BigMarbleWorld : ModuleRules
|
||||
{
|
||||
public BigMarbleWorld(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "EnhancedInput" });
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(new string[] { });
|
||||
|
||||
// Uncomment if you are using Slate UI
|
||||
// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
|
||||
|
||||
// Uncomment if you are using online features
|
||||
// PrivateDependencyModuleNames.Add("OnlineSubsystem");
|
||||
|
||||
// To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "BigMarbleWorld.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, BigMarbleWorld, "BigMarbleWorld" );
|
||||
@@ -0,0 +1,6 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "Marble/MarbleController.h"
|
||||
|
||||
#include "EnhancedInputSubsystems.h"
|
||||
|
||||
void AMarbleController::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
bShowMouseCursor = false;
|
||||
SetInputMode(FInputModeGameOnly());
|
||||
|
||||
if (PlayerCameraManager)
|
||||
{
|
||||
PlayerCameraManager->ViewPitchMin = -60.0f;
|
||||
PlayerCameraManager->ViewPitchMax = 20.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void AMarbleController::SetupInputComponent()
|
||||
{
|
||||
Super::SetupInputComponent();
|
||||
|
||||
// only add IMCs for local player controllers
|
||||
if (IsLocalPlayerController())
|
||||
{
|
||||
// Add Input Mapping Contexts
|
||||
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer()))
|
||||
{
|
||||
for (UInputMappingContext* CurrentContext : DefaultMappingContexts)
|
||||
{
|
||||
Subsystem->AddMappingContext(CurrentContext, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "Marble/MarbleMovementComponent.h"
|
||||
|
||||
#include "Components/SphereComponent.h"
|
||||
#include "DataWrappers/ChaosVDJointDataWrappers.h"
|
||||
#include "Math/UnitConversion.h"
|
||||
#include "Sound/SoundWaveProxyPlayer.h"
|
||||
|
||||
|
||||
// Sets default values for this component's properties
|
||||
UMarbleMovementComponent::UMarbleMovementComponent()
|
||||
{
|
||||
// Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
|
||||
// off to improve performance if you don't need them.
|
||||
PrimaryComponentTick.bCanEverTick = true;
|
||||
PrimaryComponentTick.TickInterval = 1.0f / 30.0f;
|
||||
|
||||
SetIsReplicatedByDefault(true);
|
||||
}
|
||||
|
||||
void UMarbleMovementComponent::SetMoveDirection(FVector WorldDirection)
|
||||
{
|
||||
WorldDirection.Z = 0.0f;
|
||||
WorldDirection = WorldDirection.GetClampedToMaxSize(1.0f);
|
||||
|
||||
CachedMoveDirection = WorldDirection;
|
||||
}
|
||||
|
||||
void UMarbleMovementComponent::BeginJump()
|
||||
{
|
||||
if (!PhysicsSphere || !IsLocallyControlling() || !IsGrounded())
|
||||
return;
|
||||
|
||||
bIsJumping = true;
|
||||
JumpHoldElapsed = 0.0f;
|
||||
PhysicsSphere->AddImpulse(FVector::UpVector * JumpInitialImpulse, NAME_None, true);
|
||||
}
|
||||
|
||||
void UMarbleMovementComponent::EndJump()
|
||||
{
|
||||
bIsJumping = false;
|
||||
}
|
||||
|
||||
bool UMarbleMovementComponent::IsGrounded() const
|
||||
{
|
||||
if (!PhysicsSphere)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const float Radius = PhysicsSphere->GetScaledSphereRadius();
|
||||
const FVector Start = PhysicsSphere->GetComponentLocation();
|
||||
const FVector End = Start - FVector::UpVector * (Radius + GroundCheckDistance);
|
||||
|
||||
FCollisionQueryParams Params;
|
||||
Params.AddIgnoredActor(GetOwner());
|
||||
|
||||
FHitResult Hit;
|
||||
return GetWorld()->LineTraceSingleByChannel(Hit, Start, End, ECC_Visibility, Params);
|
||||
}
|
||||
|
||||
// Called when the game starts
|
||||
void UMarbleMovementComponent::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
if (!IsValid(PhysicsSphere))
|
||||
PhysicsSphere = Cast<USphereComponent>(GetOwner()->GetRootComponent());
|
||||
ensureMsgf(PhysicsSphere, TEXT("Owner must have a sphere component as root"));
|
||||
}
|
||||
|
||||
// Called every frame
|
||||
void UMarbleMovementComponent::TickComponent(float DeltaTime, ELevelTick TickType,
|
||||
FActorComponentTickFunction* ThisTickFunction)
|
||||
{
|
||||
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
||||
|
||||
if (!PhysicsSphere)
|
||||
return;
|
||||
|
||||
if (IsLocallyControlling())
|
||||
TickControlling(DeltaTime);
|
||||
else
|
||||
TickProxy(DeltaTime);
|
||||
}
|
||||
|
||||
void UMarbleMovementComponent::ServerSyncTransform_Implementation(
|
||||
FVector_NetQuantize100 Location,
|
||||
FRotator Rotation,
|
||||
FVector_NetQuantize100 LinearVel,
|
||||
FVector_NetQuantize100 AngularVel)
|
||||
{
|
||||
MulticastSyncTransform(Location, Rotation, LinearVel, AngularVel);
|
||||
}
|
||||
|
||||
void UMarbleMovementComponent::MulticastSyncTransform_Implementation(
|
||||
FVector_NetQuantize100 Location,
|
||||
FRotator Rotation,
|
||||
FVector_NetQuantize100 LinearVel,
|
||||
FVector_NetQuantize100 AngularVel)
|
||||
{
|
||||
if (IsLocallyControlling())
|
||||
return;
|
||||
|
||||
ProxyTargetLocation = Location;
|
||||
ProxyTargetRotation = Rotation;
|
||||
ProxyTargetLinearVel = LinearVel;
|
||||
ProxyTargetAngularVel = AngularVel;
|
||||
bHasProxyTarget = true;
|
||||
}
|
||||
|
||||
void UMarbleMovementComponent::ServerSetMoveDirection_Implementation(FVector WorldDirection)
|
||||
{
|
||||
CachedMoveDirection = WorldDirection;
|
||||
}
|
||||
|
||||
bool UMarbleMovementComponent::IsLocallyControlling() const
|
||||
{
|
||||
const APawn* OwningPawn = Cast<APawn>(GetOwner());
|
||||
return IsValid(OwningPawn) && OwningPawn->IsLocallyControlled();
|
||||
}
|
||||
|
||||
void UMarbleMovementComponent::TickControlling(float DeltaTime)
|
||||
{
|
||||
if (!CachedMoveDirection.IsNearlyZero())
|
||||
{
|
||||
const FVector Direction = CachedMoveDirection.GetSafeNormal();
|
||||
const float Speed = CachedMoveDirection.Size();
|
||||
|
||||
const FVector TorqueAxis = FVector::CrossProduct(FVector::UpVector, Direction);
|
||||
if (PhysicsSphere->GetPhysicsAngularVelocityInRadians().Size() < MaxAngularSpeed)
|
||||
PhysicsSphere->AddTorqueInRadians(TorqueAxis * RollForce * Speed, NAME_None, true);
|
||||
|
||||
if (IsGrounded())
|
||||
{
|
||||
if (PhysicsSphere->GetPhysicsLinearVelocity().Size() < MaxLinearSpeed)
|
||||
PhysicsSphere->AddForce(Direction * MoveForce * Speed, NAME_None, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PhysicsSphere->GetPhysicsLinearVelocity().Size() < MaxLinearSpeed * AerialControlFactor)
|
||||
PhysicsSphere->AddForce(Direction * MoveForce * AerialControlFactor * Speed, NAME_None, true);
|
||||
}
|
||||
}
|
||||
if (bIsJumping)
|
||||
{
|
||||
JumpHoldElapsed += DeltaTime;
|
||||
if (JumpHoldElapsed <= MaxJumpHoldDuration)
|
||||
{
|
||||
PhysicsSphere->AddForce(FVector::UpVector * JumpHoldForce, NAME_None, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
bIsJumping = false;
|
||||
}
|
||||
}
|
||||
|
||||
SyncTimer += DeltaTime;
|
||||
const float SyncInterval = 1.0f / FMath::Max(1.0f, SyncSendRate);
|
||||
if (SyncTimer >= SyncInterval)
|
||||
{
|
||||
SyncTimer = 0.0f;
|
||||
|
||||
const FVector_NetQuantize100 Location = PhysicsSphere->GetComponentLocation();
|
||||
const FRotator Rotation = PhysicsSphere->GetComponentRotation();
|
||||
const FVector_NetQuantize100 LinearVel = PhysicsSphere->GetPhysicsLinearVelocity();
|
||||
const FVector_NetQuantize100 AngularVel = PhysicsSphere->GetPhysicsAngularVelocityInDegrees();
|
||||
|
||||
if (GetOwnerRole() == ROLE_Authority)
|
||||
{
|
||||
MulticastSyncTransform(Location, Rotation, LinearVel, AngularVel);
|
||||
}
|
||||
else
|
||||
{
|
||||
ServerSyncTransform(Location, Rotation, LinearVel, AngularVel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UMarbleMovementComponent::TickProxy(float DeltaTime)
|
||||
{
|
||||
if (!bHasProxyTarget || !IsValid(PhysicsSphere))
|
||||
return;
|
||||
|
||||
const FVector CurrentLocation = PhysicsSphere->GetComponentLocation();
|
||||
const FVector NewLocation = FMath::VInterpTo(CurrentLocation, FVector(ProxyTargetLocation), DeltaTime, ProxyCorrectionSpeed);
|
||||
|
||||
const FRotator CurrentRotation = PhysicsSphere->GetComponentRotation();
|
||||
const FRotator NewRotation = FMath::RInterpTo(CurrentRotation, FRotator(ProxyTargetRotation), DeltaTime, ProxyCorrectionSpeed);
|
||||
|
||||
PhysicsSphere->SetWorldLocationAndRotation(NewLocation, NewRotation, false, nullptr, ETeleportType::TeleportPhysics);
|
||||
PhysicsSphere->SetPhysicsLinearVelocity(FVector(ProxyTargetLinearVel));
|
||||
PhysicsSphere->SetPhysicsAngularVelocityInDegrees(FVector(ProxyTargetAngularVel));
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "Marble/MarblePawn.h"
|
||||
|
||||
#include "Components/SphereComponent.h"
|
||||
#include "Marble/MarbleMovementComponent.h"
|
||||
|
||||
// Sets default values
|
||||
AMarblePawn::AMarblePawn()
|
||||
{
|
||||
// Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it.
|
||||
PrimaryActorTick.bCanEverTick = false;
|
||||
|
||||
bReplicates = true;
|
||||
SetReplicatingMovement(false); // custom sync in movement component
|
||||
|
||||
Collider = CreateDefaultSubobject<USphereComponent>(TEXT("Collider"));
|
||||
RootComponent = Collider;
|
||||
Collider->InitSphereRadius(50.f);
|
||||
Collider->SetSimulatePhysics(true);
|
||||
Collider->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
|
||||
Collider->SetCollisionObjectType(ECC_Pawn);
|
||||
Collider->SetLinearDamping(0.1f);
|
||||
Collider->SetAngularDamping(0.3f);
|
||||
Collider->SetNotifyRigidBodyCollision(true);
|
||||
|
||||
Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
|
||||
Mesh->SetupAttachment(Collider);
|
||||
Mesh->SetCollisionEnabled(ECollisionEnabled::NoCollision);
|
||||
|
||||
MovementComponent = CreateDefaultSubobject<UMarbleMovementComponent>(TEXT("MovementComponent"));
|
||||
}
|
||||
|
||||
void AMarblePawn::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "Marble/MarblePlayerInputComponent.h"
|
||||
|
||||
#include "EnhancedInputComponent.h"
|
||||
#include "EnhancedInputSubsystems.h"
|
||||
#include "Camera/CameraComponent.h"
|
||||
#include "Marble/MarbleMovementComponent.h"
|
||||
|
||||
|
||||
// Sets default values for this component's properties
|
||||
UMarblePlayerInputComponent::UMarblePlayerInputComponent()
|
||||
{
|
||||
// Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
|
||||
// off to improve performance if you don't need them.
|
||||
PrimaryComponentTick.bCanEverTick = false;
|
||||
|
||||
}
|
||||
|
||||
void UMarblePlayerInputComponent::BindInput(UInputComponent* InputComponent)
|
||||
{
|
||||
if (APlayerController* PC = Cast<APlayerController>(GetOwner()->GetInstigatorController()))
|
||||
{
|
||||
if (UEnhancedInputLocalPlayerSubsystem* Subsystem =
|
||||
ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PC->GetLocalPlayer()))
|
||||
{
|
||||
Subsystem->AddMappingContext(DefaultMappingContext, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (UEnhancedInputComponent* EIC = Cast<UEnhancedInputComponent>(InputComponent))
|
||||
{
|
||||
EIC->BindAction(MoveAction, ETriggerEvent::Triggered, this, &ThisClass::OnMove);
|
||||
EIC->BindAction(MoveAction, ETriggerEvent::Completed, this, &ThisClass::OnMove);
|
||||
EIC->BindAction(MoveAction, ETriggerEvent::Canceled, this, &ThisClass::OnMove);
|
||||
|
||||
EIC->BindAction(LookAction, ETriggerEvent::Triggered, this, &ThisClass::OnLook);
|
||||
|
||||
EIC->BindAction(JumpAction, ETriggerEvent::Started, this, &ThisClass::OnJumpStarted);
|
||||
EIC->BindAction(JumpAction, ETriggerEvent::Completed, this, &ThisClass::OnJumpReleased);
|
||||
EIC->BindAction(JumpAction, ETriggerEvent::Canceled, this, &ThisClass::OnJumpReleased);
|
||||
}
|
||||
}
|
||||
|
||||
// Called when the game starts
|
||||
void UMarblePlayerInputComponent::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
if (!IsValid(MovementComponent))
|
||||
MovementComponent = GetOwner()->FindComponentByClass<UMarbleMovementComponent>();
|
||||
if (!IsValid(CameraComponent))
|
||||
CameraComponent = GetOwner()->FindComponentByClass<UCameraComponent>();
|
||||
}
|
||||
|
||||
void UMarblePlayerInputComponent::OnMove(const FInputActionValue& Value)
|
||||
{
|
||||
if (!IsValid(MovementComponent) || !IsValid(CameraComponent))
|
||||
return;
|
||||
|
||||
const FVector2D Input = Value.Get<FVector2D>();
|
||||
const FRotator YawRot(0.0f, CameraComponent->GetComponentRotation().Yaw, 0.0f);
|
||||
const FVector Forward = FRotationMatrix(YawRot).GetUnitAxis(EAxis::X);
|
||||
const FVector Right = FRotationMatrix(YawRot).GetUnitAxis(EAxis::Y);
|
||||
|
||||
MovementComponent->SetMoveDirection(Forward * Input.Y + Right * Input.X);
|
||||
}
|
||||
|
||||
void UMarblePlayerInputComponent::OnLook(const FInputActionValue& Value)
|
||||
{
|
||||
APawn* OwningPawn = Cast<APawn>(GetOwner());
|
||||
if (!IsValid(OwningPawn))
|
||||
return;
|
||||
|
||||
const FVector2D Input = Value.Get<FVector2D>();
|
||||
|
||||
OwningPawn->AddControllerYawInput(Input.X * LookYawRate);
|
||||
OwningPawn->AddControllerPitchInput(-Input.Y * LookPitchRate);
|
||||
}
|
||||
|
||||
void UMarblePlayerInputComponent::OnJumpStarted(const FInputActionValue& Value)
|
||||
{
|
||||
if (IsValid(MovementComponent))
|
||||
MovementComponent->BeginJump();
|
||||
}
|
||||
|
||||
void UMarblePlayerInputComponent::OnJumpReleased(const FInputActionValue& Value)
|
||||
{
|
||||
if (IsValid(MovementComponent))
|
||||
MovementComponent->EndJump();
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "Marble/PlayerMarblePawn.h"
|
||||
|
||||
#include "Camera/CameraComponent.h"
|
||||
#include "GameFramework/SpringArmComponent.h"
|
||||
#include "Marble/MarblePlayerInputComponent.h"
|
||||
|
||||
|
||||
// Sets default values
|
||||
APlayerMarblePawn::APlayerMarblePawn()
|
||||
{
|
||||
SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));
|
||||
SpringArm->SetupAttachment(RootComponent);
|
||||
SpringArm->TargetArmLength = 650.0f;
|
||||
SpringArm->bDoCollisionTest = true;
|
||||
SpringArm->bEnableCameraLag = true;
|
||||
SpringArm->CameraLagSpeed = 6.0f;
|
||||
SpringArm->bUsePawnControlRotation = true;
|
||||
|
||||
Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
|
||||
Camera->SetupAttachment(SpringArm, USpringArmComponent::SocketName);
|
||||
|
||||
MarbleInputComponent = CreateDefaultSubobject<UMarblePlayerInputComponent>(TEXT("PlayerInputComponent"));
|
||||
}
|
||||
|
||||
// Called to bind functionality to input
|
||||
void APlayerMarblePawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
|
||||
{
|
||||
Super::SetupPlayerInputComponent(PlayerInputComponent);
|
||||
|
||||
MarbleInputComponent->BindInput(PlayerInputComponent);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameFramework/PlayerController.h"
|
||||
#include "MarbleController.generated.h"
|
||||
|
||||
class UInputMappingContext;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class BIGMARBLEWORLD_API AMarbleController : public APlayerController
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
protected:
|
||||
|
||||
/** Input Mapping Contexts */
|
||||
UPROPERTY(EditAnywhere, Category ="Input|Input Mappings")
|
||||
TArray<UInputMappingContext*> DefaultMappingContexts;
|
||||
|
||||
/** Gameplay initialization */
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
/** Input mapping context setup */
|
||||
virtual void SetupInputComponent() override;
|
||||
|
||||
};
|
||||
@@ -0,0 +1,118 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Components/ActorComponent.h"
|
||||
#include "MarbleMovementComponent.generated.h"
|
||||
|
||||
class USphereComponent;
|
||||
|
||||
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
|
||||
class BIGMARBLEWORLD_API UMarbleMovementComponent : public UActorComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
// Sets default values for this component's properties
|
||||
UMarbleMovementComponent();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Marble|Movement")
|
||||
void SetMoveDirection(FVector WorldDirection);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Marble|Movement")
|
||||
void BeginJump();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Marble|Jump")
|
||||
void EndJump();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Marble|State")
|
||||
bool IsGrounded() const;
|
||||
|
||||
// Called when the game starts
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
// Called every frame
|
||||
virtual void TickComponent(float DeltaTime, ELevelTick TickType,
|
||||
FActorComponentTickFunction* ThisTickFunction) override;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Marble|Network")
|
||||
bool IsLocallyControlling() const;
|
||||
|
||||
protected:
|
||||
|
||||
UFUNCTION(Server, Unreliable)
|
||||
void ServerSetMoveDirection(FVector WorldDirection);
|
||||
|
||||
UFUNCTION(Server, Unreliable)
|
||||
void ServerSyncTransform(
|
||||
FVector_NetQuantize100 Location,
|
||||
FRotator Rotation,
|
||||
FVector_NetQuantize100 LinearVel,
|
||||
FVector_NetQuantize100 AngularVel
|
||||
);
|
||||
|
||||
UFUNCTION(NetMulticast, Unreliable)
|
||||
void MulticastSyncTransform(
|
||||
FVector_NetQuantize100 Location,
|
||||
FRotator Rotation,
|
||||
FVector_NetQuantize100 LinearVel,
|
||||
FVector_NetQuantize100 AngularVel
|
||||
);
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Marble|Movement")
|
||||
float RollForce = 1200.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Marble|Movement")
|
||||
float MaxAngularSpeed = 8.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Marble|Movement")
|
||||
float MoveForce = 400.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Marble|Movement")
|
||||
float MaxLinearSpeed = 1200.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Marble|Movement")
|
||||
float AerialControlFactor = 0.3f;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Marble|Jump")
|
||||
float JumpInitialImpulse = 350.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Marble|Jump")
|
||||
float JumpHoldForce = 1800.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Marble|Jump")
|
||||
float MaxJumpHoldDuration = 0.3f;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Marble|Jump")
|
||||
float GroundCheckDistance = 5.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Marble|Network")
|
||||
float SyncSendRate = 20.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Marble|Network")
|
||||
float ProxyCorrectionSpeed = 10.0f;
|
||||
|
||||
private:
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<USphereComponent> PhysicsSphere; // Resolved from owner
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Marble|Movement", meta = (AllowPrivateAccess = "true"))
|
||||
FVector CachedMoveDirection = FVector::ZeroVector;
|
||||
|
||||
float SyncTimer = 0.0f;
|
||||
|
||||
bool bIsJumping = false;
|
||||
float JumpHoldElapsed = 0.0f;
|
||||
|
||||
FVector_NetQuantize100 ProxyTargetLocation;
|
||||
FRotator ProxyTargetRotation = FRotator::ZeroRotator;
|
||||
FVector_NetQuantize100 ProxyTargetLinearVel;
|
||||
FVector_NetQuantize100 ProxyTargetAngularVel;
|
||||
bool bHasProxyTarget = false;
|
||||
|
||||
void TickControlling(float DeltaTime);
|
||||
void TickProxy(float DeltaTime);
|
||||
|
||||
};
|
||||
@@ -0,0 +1,37 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameFramework/Pawn.h"
|
||||
#include "MarblePawn.generated.h"
|
||||
|
||||
class USphereComponent;
|
||||
class UStaticMeshComponent;
|
||||
class UMarbleMovementComponent;
|
||||
|
||||
UCLASS()
|
||||
class BIGMARBLEWORLD_API AMarblePawn : public APawn
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
// Sets default values for this pawn's properties
|
||||
AMarblePawn();
|
||||
|
||||
UMarbleMovementComponent* GetMarbleMovement() const { return MovementComponent; }
|
||||
|
||||
void BeginPlay() override;
|
||||
|
||||
protected:
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
|
||||
TObjectPtr<USphereComponent> Collider;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
|
||||
TObjectPtr<UStaticMeshComponent> Mesh;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
|
||||
TObjectPtr<UMarbleMovementComponent> MovementComponent;
|
||||
|
||||
};
|
||||
@@ -0,0 +1,62 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Components/ActorComponent.h"
|
||||
#include "MarblePlayerInputComponent.generated.h"
|
||||
|
||||
|
||||
class UCameraComponent;
|
||||
class UMarbleMovementComponent;
|
||||
struct FInputActionValue;
|
||||
class UInputAction;
|
||||
class UInputMappingContext;
|
||||
class USpringArmComponent;
|
||||
|
||||
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
|
||||
class BIGMARBLEWORLD_API UMarblePlayerInputComponent : public UActorComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
// Sets default values for this component's properties
|
||||
UMarblePlayerInputComponent();
|
||||
|
||||
void BindInput(UInputComponent* InputComponent);
|
||||
|
||||
// Called when the game starts
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, Category = "Input")
|
||||
TObjectPtr<UInputMappingContext> DefaultMappingContext;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, Category = "Input")
|
||||
TObjectPtr<UInputAction> MoveAction;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, Category = "Input")
|
||||
TObjectPtr<UInputAction> LookAction;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, Category = "Input")
|
||||
TObjectPtr<UInputAction> JumpAction;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Input|Look")
|
||||
float LookYawRate = 1.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Input|Look")
|
||||
float LookPitchRate = 1.0f;
|
||||
|
||||
private:
|
||||
|
||||
void OnMove(const FInputActionValue& Value);
|
||||
void OnLook(const FInputActionValue& Value);
|
||||
void OnJumpStarted(const FInputActionValue& Value);
|
||||
void OnJumpReleased(const FInputActionValue& Value);
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UMarbleMovementComponent> MovementComponent;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UCameraComponent> CameraComponent;
|
||||
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "MarblePawn.h"
|
||||
#include "PlayerMarblePawn.generated.h"
|
||||
|
||||
class UCameraComponent;
|
||||
class UMarblePlayerInputComponent;
|
||||
class USpringArmComponent;
|
||||
|
||||
UCLASS()
|
||||
class BIGMARBLEWORLD_API APlayerMarblePawn : public AMarblePawn
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
// Sets default values for this pawn's properties
|
||||
APlayerMarblePawn();
|
||||
|
||||
protected:
|
||||
|
||||
// Called to bind functionality to input
|
||||
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, Category = "Components")
|
||||
TObjectPtr<USpringArmComponent> SpringArm;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, Category = "Components")
|
||||
TObjectPtr<UCameraComponent> Camera;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, Category = "Components")
|
||||
TObjectPtr<UMarblePlayerInputComponent> MarbleInputComponent;
|
||||
|
||||
};
|
||||
@@ -0,0 +1,15 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
using UnrealBuildTool;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class BigMarbleWorldEditorTarget : TargetRules
|
||||
{
|
||||
public BigMarbleWorldEditorTarget( TargetInfo Target) : base(Target)
|
||||
{
|
||||
Type = TargetType.Editor;
|
||||
DefaultBuildSettings = BuildSettingsVersion.V7;
|
||||
IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_8;
|
||||
ExtraModuleNames.Add("BigMarbleWorld");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user