Starting multiplayer Marble game

This commit is contained in:
2026-09-01 21:20:20 +02:00
parent 652e1bfa8b
commit b107357501
30 changed files with 1177 additions and 0 deletions
+15
View File
@@ -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
}
}
+6
View File
@@ -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" );
+6
View File
@@ -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;
};
+15
View File
@@ -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");
}
}