In multiplayer game I want to keep all useful items simulating physics and disable physics when character grab them. I found that physics is simulating on both sides(server and client), and I should call some NetMulticast function what disable all things I want. But this function is in interface
#pragma once
#include "PickableInterface.generated.h"
UINTERFACE(Blueprintable)
class UPickableInterface : public UInterface
{
GENERATED_UINTERFACE_BODY()
};
class IPickableInterface
{
GENERATED_IINTERFACE_BODY()
public:
UFUNCTION(NetMulticast, Reliable, Category = "Pickable Interface")
void OnPickUp();
};
And I have Weapon class implementing OnPickUp function
#pragma once
#include "GameFramework/Actor.h"
#include "Interfaces/PickableInterface.h"
#include "ZzzzzWeapon.generated.h"
UCLASS()
class ZZZZZ_API AZzzzzWeapon : public AActor, public IPickableInterface
{
GENERATED_BODY()
public:
virtual void OnPickUp_Implementation() override;
};
void AZzzzzWeapon::OnPickUp_Implementation()
{
UE_LOG(ZzzzzWeaponLog, Log, TEXT("%s is picked up"), *this->GetName());
// WeaponBody is SkeletalMeshComponent used as Root
WeaponBody->SetSimulatePhysics(false);
WeaponBody->SetCollisionEnabled(ECollisionEnabled::NoCollision);
}
Item pickng up works next way: OnActorBeginOverlap calls server function TryToPickUp, which check is overlapped actor implements PickableInterface or not and attach it to Character and disabling physics if it is.
#pragma once
#include "GameFramework/Character.h"
#include "Player/ZzzzzCharacterMovementComponent.h"
#include "ZzzzzCharacter.generated.h"
UCLASS()
class ZZZZZ_API AZzzzzCharacter : public ACharacter
{
GENERATED_BODY()
public:
UFUNCTION()
void OnZzzzzCharacterBeginOverlap(AActor* OverlappedActor, AActor* OtherActor);
UFUNCTION(Server, WithValidation, Reliable)
void TryToPickUp(AActor* PickUpActor);
void TryToPickUp_Implementation(AActor* PickUpActor);
bool TryToPickUp_Validate(AActor* PickUpActor) { return true; }
public:
UPROPERTY(Replicated, EditDefaultsOnly, BlueprintReadOnly, Category = "Zzzzz Character Items", meta = (AllowPrivateAccess = true))
FName HandItemSocket;
protected:
UFUNCTION(NetMulticast, Reliable)
void GrabToHand(AActor* GrabActor);
void GrabToHand_Implementation(AActor* GrabActor);
};
void AZzzzzCharacter::OnZzzzzCharacterBeginOverlap(AActor* OverlappedActor, AActor* OtherActor)
{
if (Role < ROLE_Authority)
{
TryToPickUp(OtherActor);
}
}
void AZzzzzCharacter::TryToPickUp_Implementation(AActor* PickUpActor)
{
if (Role == ROLE_Authority)
{
if (PickUpActor != nullptr &&
PickUpActor->GetClass()->ImplementsInterface(UPickableInterface::StaticClass()))
{
UE_LOG(ZzzzzCharacterLog, Warning, TEXT("%s is trying to pick up %s"), *this->GetName(), *PickUpActor->GetName());
PickUpActor->SetOwner(this);
//IPickableInterface::Execute_OnPickUp(PickUpActor);<---- This interface NetMulticast function call just doesn't work
GrabToHand(PickUpActor);
}
}
}
void AZzzzzCharacter::GrabToHand_Implementation(AActor* GrabActor)
{
if (GrabActor)
{
IPickableInterface::Execute_OnPickUp(GrabActor); //<---- But here it works just like ordinary function
GrabActor->AttachToComponent(GetMesh(), FAttachmentTransformRules::SnapToTargetIncludingScale, HandItemSocket);
}
}
Problem is NetMulticast function(but from interface) doesn’t fire as expected, but works like simple function in other NetMulticast function(character function for now).
Are UE4 C++ interfaces not designed for Remote Procedure Calls, or in this case main problem is bad code design?