다양한 기록

[ChronoSpace] Change Level in Multiplay 본문

언리얼 엔진/ChronoSpace

[ChronoSpace] Change Level in Multiplay

라구넹 2025. 2. 15. 03:47

ClockworkLabyrinth 작업 중이다

Key를 다 바치면 기본 맵으로 이동시켜야 한다

그런데 멀티니까 서버랑 클라이언트 전부 이동이 필요하다

 

찾아보니까 정말 쉬운데, 서버가 ServerTravle 하면 리슨 서버랑 클라이언트 전부 알아서 이동된다

 

// Fill out your copyright notice in the Description page of Project Settings.


#include "Actor/CSLabyrinthKeyAltar.h"
#include "Character/CSCharacterPlayer.h"
#include "Components/StaticMeshComponent.h"
#include "Components/SphereComponent.h"
#include "Physics/CSCollision.h"
#include "Subsystem/CSLabyrinthKeyWorldSubsystem.h"
#include "Blueprint/UserWidget.h"
#include "Components/WidgetComponent.h"
#include "ChronoSpace.h"
#include "Engine/World.h"

// Sets default values
ACSLabyrinthKeyAltar::ACSLabyrinthKeyAltar()
{
	bReplicates = true;

	// Static Mesh
	StaticMeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
	StaticMeshComp->SetRelativeLocation(FVector(0.0f, 0.0f, 0.0f));
	RootComponent = StaticMeshComp;
	StaticMeshComp->SetCollisionProfileName(CPROFILE_CSCAPSULE);
	StaticMeshComp->SetIsReplicated(true);

	// SphereTrigger
	SphereTrigger = CreateDefaultSubobject<USphereComponent>(TEXT("GravitySphereTrigger"));
	SphereTrigger->SetSphereRadius(TriggerRange, true);
	SphereTrigger->SetupAttachment(StaticMeshComp);
	SphereTrigger->SetRelativeLocation(FVector(40.0f, 60.0f, 0.0f));
	SphereTrigger->SetCollisionProfileName(CPROFILE_CSTRIGGER);
	SphereTrigger->SetIsReplicated(true);


	static ConstructorHelpers::FObjectFinder<UStaticMesh> StaticMeshRef(TEXT("/Script/Engine.StaticMesh'/Game/Mesh/StaticMesh/SM_SM_Altar.SM_SM_Altar'"));
	if (StaticMeshRef.Object)
	{
		StaticMeshComp->SetStaticMesh(StaticMeshRef.Object);
	}

	SphereTrigger->OnComponentBeginOverlap.AddDynamic(this, &ACSLabyrinthKeyAltar::OnTriggerBeginOverlapCallback);
	SphereTrigger->OnComponentEndOverlap.AddDynamic(this, &ACSLabyrinthKeyAltar::OnTriggerEndOverlapCallback);

	// Widget
	InteractionPromptComponent = CreateDefaultSubobject<UWidgetComponent>(TEXT("InteractionPromptComponent"));
	InteractionPromptComponent->SetupAttachment(SphereTrigger);
	InteractionPromptComponent->SetRelativeLocation(FVector(0.0f, 0.0f, 100.0f));

	static ConstructorHelpers::FClassFinder<UUserWidget> InteractionPromptWidgetRef(TEXT("/Game/Blueprint/UI/BP_InteractionPrompt.BP_InteractionPrompt_C"));
	if (InteractionPromptWidgetRef.Class)
	{
		InteractionPromptComponent->SetWidgetClass(InteractionPromptWidgetRef.Class);
		InteractionPromptComponent->SetWidgetSpace(EWidgetSpace::Screen);
		InteractionPromptComponent->SetDrawSize(FVector2D(500.0f, 30.f));
		InteractionPromptComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision);
	}

	InteractionPromptComponent->SetVisibility(false);

	RequiredKeyCount = 3;
}

void ACSLabyrinthKeyAltar::OnTriggerBeginOverlapCallback(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepHitResult)
{
	ACSCharacterPlayer* Player = Cast<ACSCharacterPlayer>(OtherActor);

	if (Player)
	{
		Player->OnInteract.Clear();
		InteractionPromptComponent->SetVisibility(true);
		Player->OnInteract.AddDynamic(this, &ACSLabyrinthKeyAltar::Interact);
	}
}

void ACSLabyrinthKeyAltar::OnTriggerEndOverlapCallback(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
	ACSCharacterPlayer* Player = Cast<ACSCharacterPlayer>(OtherActor);

	if (Player)
	{
		InteractionPromptComponent->SetVisibility(false);
		Player->OnInteract.Clear();
	}
}

void ACSLabyrinthKeyAltar::Interact()
{
	UCSLabyrinthKeyWorldSubsystem* LabyrinthKeySubsystem = GetWorld()->GetSubsystem<UCSLabyrinthKeyWorldSubsystem>();

	if (LabyrinthKeySubsystem)
	{
		int NowKeyCount = LabyrinthKeySubsystem->GetLabyrinthKeyCount();
		
		if ( NowKeyCount >= RequiredKeyCount )
		{
			ChangeLevel();
		}
	}
}

void ACSLabyrinthKeyAltar::ChangeLevel()
{
	if ( HasAuthority() && GetWorld() )
	{
		GetWorld()->ServerTravel(TEXT("L_MapClockworkLabyrinth?listen"));
	}
}

주의 할 점이 있다면 서버에서 실행되도록 확실히 할 것

애초에 저 Interact가 CharacterPlayer에서 RPC로 처리해둬서 Server만 발동하도록 처리해놔서 별다른 처리를 해줄 필욘 없었는데, 그렇지 않다면 게임 모드에서 처리하거나 클라이언트에서 쓰면 RPC로 서버에서 작동하도록 하거나 해주자

 

 

임시로 맵 설정을 해뒀는데 멀쩡히 작동한다

 

하는 김에 메쉬도 만들어주고

 

 

맵 옮겨서도 테스트 완료

 

이제 저 Key를 맵에 흩뿌리면 된다