Клиент не может вызвать RPC-сервер даже при наличии действительного владельца сети.C++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 Клиент не может вызвать RPC-сервер даже при наличии действительного владельца сети.

Сообщение Anonymous »

Это первый актер, который я создал для многопользовательской игры с репликацией, поэтому, если вы считаете, что мне следовало использовать другой метод, скажите мне.
Я использую 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
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»