Это первый актер, который я создал для многопользовательской игры с репликацией, поэтому, если вы считаете, что мне следовало использовать другой метод, скажите мне.
Я использую UE5.4 с двумя игроками и как сетевое соединение, я использую сервер прослушивания.
Поэтому я пытаюсь создать простую дверь, с которой вы можете взаимодействовать, чтобы открыть или закрыть ее. Когда вы взаимодействуете с дверью, клиент вызывает серверный RPC с именем ServerInteract, этот RPC обновляет атрибут bOpen актера двери. Этот атрибут помечен как ReplicationdUsing, поэтому его следует реплицировать на всех клиентах, а также вызывать функцию OnRep на всех клиентах. Эта функция OnRep воспроизводит анимацию открытия или закрытия на основе состояния bOpen.
Моя проблема в том, что когда я взаимодействую с дверью с клиента 0, который также является хостом/сервером, репликация работает отлично. Но когда я взаимодействую с клиентом 1, который является не хостом, а простым клиентом, ServerInteract RPC даже не вызывается, даже если у владельца актера есть действительное соединение.
Вы можете увидеть на видео тест, где логи ясно отражают мою точку зрения.
Видео на YouTube
Door.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "../InteractiveActor.h"
#include "Door.generated.h"
UCLASS()
class ESCAPEGAME_API ADoor : public AInteractiveActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ADoor();
// Handle interaction
virtual void ServerInteract_Implementation(APawn* InteractionSender) override;
virtual void GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const override;
UFUNCTION(BlueprintCallable)
bool ToggleDoor();
UFUNCTION()
void OnRep_bOpen();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
protected:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Door)
UAnimSequence* DoorOpening_Animation;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Door)
UAnimSequence* DoorClosing_Animation;
UPROPERTY(ReplicatedUsing=OnRep_bOpen ,EditAnywhere, BlueprintReadOnly, Category = Door)
bool bOpen;
public:
UPROPERTY(EditAnywhere, category = Door)
USkeletalMeshComponent* DoorSkeletalMesh;
UPROPERTY(EditAnywhere, category = Door)
USceneComponent* DoorRoot;
};
Door.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "Door.h"
#include "Net/UnrealNetwork.h"
// Sets default values
ADoor::ADoor()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = false;
DoorRoot = CreateDefaultSubobject(TEXT("DoorRoot"));
SetRootComponent(DoorRoot);
DoorSkeletalMesh = CreateDefaultSubobject("DoorMesh");
DoorSkeletalMesh->SetupAttachment(DoorRoot);
// Initiate variables
bOpen = false;
bReplicates = true;
}
// Called when the game starts or when spawned
void ADoor::BeginPlay()
{
Super::BeginPlay();
}
bool ADoor::ToggleDoor()
{
UE_LOG(LogTemp, Warning, TEXT("ToggleDoor : This actor has %s"), ( HasAuthority() ? TEXT("authority") : TEXT("no authority") ));
bOpen = !bOpen;
if (HasAuthority())
{
// if bOpen changed to true play opening animation if it changed to false play closing animation.
DoorSkeletalMesh->PlayAnimation(bOpen ? DoorOpening_Animation : DoorClosing_Animation, false);
}
return bOpen;
}
void ADoor::OnRep_bOpen()
{
UE_LOG(LogTemp, Warning, TEXT("OnRep_bOpen Has authority : %s"), (HasAuthority() ? TEXT("yes") : TEXT("no")));
UE_LOG(LogTemp, Warning, TEXT("bOpen : %s"), (bOpen ? TEXT("yes") : TEXT("no")));
// if bOpen changed to true play opening animation if it changed to false play closing animation.
DoorSkeletalMesh->PlayAnimation(bOpen ? DoorOpening_Animation : DoorClosing_Animation, false);
}
void ADoor::ServerInteract_Implementation(APawn* player)
{
Super::ServerInteract_Implementation(player);
UE_LOG(LogTemp, Warning, TEXT("Server : ServerInteract"));
ToggleDoor();
}
void ADoor::GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(ADoor, bOpen);
}
InteractiveActor.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "InteractiveActor.generated.h"
UCLASS(Abstract)
class ESCAPEGAME_API AInteractiveActor : public AActor
{
GENERATED_BODY()
public:
// Interact function
UFUNCTION(Server, Reliable, WithValidation)
virtual void ServerInteract(APawn* InteractionSender);
virtual void ServerInteract_Implementation(APawn* InteractionSender);
virtual bool ServerInteract_Validate(APawn* InteractionSender);
};
InteractiveActor.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "InteractiveActor.h"
void AInteractiveActor::ServerInteract_Implementation(APawn* InteractionSender)
{
UE_LOG(LogTemp, Warning, TEXT("ServerInteract with %s, Has authority: %s"), *InteractionSender->GetName(), (HasAuthority() ? TEXT("Yes") : TEXT("No")));
}
bool AInteractiveActor::ServerInteract_Validate(APawn* InteractionSender)
{
return true;
}
Функция взаимодействия с актером игрока, которая вызывается при нажатии f.
void AEscapeGameCharacter::Interact()
{
UE_LOG(LogTemp, Warning, TEXT("AEscapeGameCharacter::Interact"));
FVector StartLocation = FirstPersonCameraComponent->GetComponentLocation();
FVector EndLocation = FirstPersonCameraComponent->GetForwardVector() * 200 + StartLocation;
FHitResult Hit;
GetWorld()->LineTraceSingleByChannel(Hit, StartLocation, EndLocation, ECC_Visibility);
DrawDebugLine(GetWorld(), StartLocation, EndLocation, FColor::Red, false, 5, 0, 5);
if (!Hit.bBlockingHit) { return; }
if (Hit.GetActor()->IsA(AInteractiveActor::StaticClass()))
{
AInteractiveActor* InteractiveActor = Cast(Hit.GetActor());
if (AEscapeGamePlayerController* controller = Cast(GetController()))
{
UE_LOG(LogTemp, Warning, TEXT("Net Rep Responsible Owner: %s"), (HasNetOwner() ? TEXT("Yes") : TEXT("No")));
InteractiveActor->SetOwner(this);
InteractiveActor->ServerInteract(this);
}
} else
{
UE_LOG(LogTemp, Warning, TEXT("Hitted something"));
}
}
Подробнее здесь: https://stackoverflow.com/questions/791 ... d-netowner
Клиент не может вызвать RPC-сервер даже при наличии действительного владельца сети. ⇐ C++
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
AppHarbor – /order/rpc.ashx(1): ошибка ASPPARSE: не удалось создать тип «web.order.rpc»
Anonymous » » в форуме C# - 0 Ответы
- 42 Просмотры
-
Последнее сообщение Anonymous
-