Announcement

Collapse
No announcement yet.

Replication Hell - the gift that keeps on giving

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • replied
    You don't seem to call the superclass. Might be something?

    Leave a comment:


  • replied
    You need to add

    SetRemoteRoleForBackwardsCompat(ROLE_SimulatedProxy);

    To your constructor otherwise the default RemoteRole will be ROLE_None

    Leave a comment:


  • replied
    What I have on my pickup item. It replicates on both client and server. Maybe replicating location also

    void APickupItem::GetLifetimeReplicatedProps(TArray<FLifetimeProperty> & OutLifetimeProps) const
    {
    Super::GetLifetimeReplicatedProps(OutLifetimeProps);

    DOREPLIFETIME(APickupItem, Instigator);
    DOREPLIFETIME(APickupItem, ReplicatedLocation);

    Leave a comment:


  • replied
    APickupItem::APickupItem(const FObjectInitializer & ObjectInitializer)
    : Super(ObjectInitializer)
    {
    Mesh = ObjectInitializer.CreateDefaultSubobject<USkeletalMeshComponent>(this, TEXT("Mesh"));
    RootComponent = Mesh;
    Mesh->SetCollisionProfileName(FName(TEXT("PhysicsActor")));
    Mesh->SetCollisionResponseToAllChannels(ECR_Ignore);
    Mesh->SetCollisionResponseToChannel(ECC_WorldStatic, ECR_Block);
    Mesh->SetCollisionResponseToChannel(ECC_GameTraceChannel1, ECR_Block);
    Mesh->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
    Mesh->CanCharacterStepUpOn = ECanBeCharacterBase::ECB_No;
    Mesh->bEnablePhysicsOnDedicatedServer = true;
    Mesh->SetSimulatePhysics(true);
    Mesh->CanCharacterStepUpOn = ECanBeCharacterBase::ECB_No;

    WeaponComponent = ObjectInitializer.CreateOptionalDefaultSubobject<UPickupComponent>(this, TEXT("New_weapon"));
    WeapontComponent->SetupAttachment(Mesh, FName(TEXT("Gun_Root")));

    bReplicates = true;
    bAlwaysRelevant = true;
    PrimaryActorTick.bCanEverTick = true;
    PrimaryActorTick.TickInterval = 0.5f;

    Leave a comment:


  • started a topic Replication Hell - the gift that keeps on giving

    Replication Hell - the gift that keeps on giving

    Right about the time I started thinking I was getting the hang of Unreal and replication in general, I ran into an issue that I have not been able to overcome.

    When spawning a new actor, I'm unable to get replication to the clients. I've spent a lot of time on this and just can't figure it out.

    PickupBase - this class is the base class for all future pickup classes in my game

    RiflePickup - this class is a weapon pickup class derived from PickupBase

    ShooterCPPGameMode - this is my Game Mode class and where I am spawning my pickups for now.

    The spawning of my weapon pickups (RiflePickup) is working fine on the server, but it won't replicate to the clients.

    APickupBase.h

    Code:
    UENUM(BlueprintType)        
    enum class EWeapon : uint8
    {
        EW_AK47     UMETA(DisplayName = "AK-47"),
        EW_AR15     UMETA(DisplayName = "AR-15"),
        EW_SMG11    UMETA(DisplayName = "SMG-11"),
        EW_ASVAL    UMETA(DisplayName = "AS VAL"),
        EW_SUB        UMETA(DisplayName = "Sub")
    };
    
    UCLASS()
    class SHOOTERCPP_API APickupBase : public AActor
    {
        GENERATED_BODY()
    
    public:    
        // Sets default values for this actor's properties
        APickupBase();
    
        virtual void Initialize(EWeapon weapon);
    
    
    protected:
        // Called when the game starts or when spawned
        virtual void BeginPlay() override;    
    
        UPROPERTY(Replicated)
        UStaticMeshComponent* weaponMeshComponent;
        UPROPERTY(Replicated)
        UBoxComponent* boxComponent;    
    
    public:    
        // Called every frame
        virtual void Tick(float DeltaTime) override;
    
    private:    
    
    };

    APickupBase.cpp

    Code:
    #include "PickupBase.h"
    #include "ConstructorHelpers.h"
    #include "Components/BoxComponent.h"
    #include "Components/StaticMeshComponent.h"
    #include "UnrealNetwork.h"
    
    // Sets default values
    APickupBase::APickupBase()
    {
        // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
        PrimaryActorTick.bCanEverTick = true;
        bReplicates = true;
        bReplicateMovement = true;
    
        // Every weapon in the game will have a box collider, static mesh and an actual type to spawn for use
        boxComponent = CreateDefaultSubobject<UBoxComponent>(TEXT("Box Comp"));
        boxComponent->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
    
        weaponMeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Weapon Mesh Comp"));
        weaponMeshComponent->SetupAttachment(boxComponent);    
    
        boxComponent->SetWorldScale3D(FVector(1.f, 1.0f, 1.0f));
        boxComponent->SetBoxExtent(FVector(60.f, 32.f, 32.f));    
    }
    
    void APickupBase::Initialize(EWeapon weapon)
    {
        // nothing to do here in the base class
    }
    
    // Called when the game starts or when spawned
    void APickupBase::BeginPlay()
    {
        Super::BeginPlay();
    }
    
    // Called every frame
    void APickupBase::Tick(float DeltaTime)
    {
        Super::Tick(DeltaTime);
    }
    
    void APickupBase::GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const
    {
        Super::GetLifetimeReplicatedProps(OutLifetimeProps);
    
        DOREPLIFETIME(APickupBase, weaponMeshComponent);
        DOREPLIFETIME(APickupBase, boxComponent);
    }

    ARiflePickup.h (notice this is derived from APickupBase)

    Code:
    #include "CoreMinimal.h"
    #include "PickupBase.h"
    #include "RiflePickup.generated.h"
    
    /**
     * 
     */
    UCLASS()
    class SHOOTERCPP_API ARiflePickup : public APickupBase
    {
        GENERATED_BODY()
    
    public:
        ARiflePickup();
    
        virtual void Initialize(EWeapon weapon) override;
    
    protected:
    
        // Weapon meshes
        UStaticMesh* ak47Mesh;
        UStaticMesh* ar15Mesh;
        UStaticMesh* kaValMesh;
        UStaticMesh* smg11Mesh;
        UStaticMesh* ak47uMesh;
    
    };

    ARiflePickup.cpp (notice this is derived from APickupBase)

    Code:
    #include "RiflePickup.h"
    #include "ConstructorHelpers.h"
    #include "Components/BoxComponent.h"
    #include "Components/StaticMeshComponent.h"
    #include "UnrealNetwork.h"
    
    ARiflePickup::ARiflePickup()
    {
        bReplicates = true;
        bReplicateMovement = true;
    
        static ConstructorHelpers::FObjectFinder<UStaticMesh> ak47Asset(TEXT("/Game/FPS_Weapon_Bundle/Weapons/Meshes/Ka47/SM_KA47_X"));
        ak47Mesh = ak47Asset.Object;
    
        static ConstructorHelpers::FObjectFinder<UStaticMesh> ar15Asset(TEXT("/Game/FPS_Weapon_Bundle/Weapons/Meshes/AR4/SM_AR4_X"));
        ar15Mesh = ar15Asset.Object;
    
        static ConstructorHelpers::FObjectFinder<UStaticMesh> kaValAsset(TEXT("/Game/FPS_Weapon_Bundle/Weapons/Meshes/Ka_Val/SM_KA_Val_X"));
        kaValMesh = kaValAsset.Object;
    
        static ConstructorHelpers::FObjectFinder<UStaticMesh> smg11Asset(TEXT("/Game/FPS_Weapon_Bundle/Weapons/Meshes/SMG11/SM_SMG11_X"));
        smg11Mesh = smg11Asset.Object;
    
        static ConstructorHelpers::FObjectFinder<UStaticMesh> ak47uAsset(TEXT("/Game/FPS_Weapon_Bundle/Weapons/Meshes/KA74U/SM_KA74U_X"));
        ak47uMesh = ak47uAsset.Object;
    }
    
    void ARiflePickup::Initialize(EWeapon weapon)
    {
        FVector meshOffset;
        UStaticMesh* weaponMesh;
    
        switch (weapon)
        {
        case EWeapon::EW_AK47:
        {
            weaponMesh = ak47Mesh;
            meshOffset = FVector(-15.f, 0.f, 0.f);
            break;
        }
        case EWeapon::EW_AR15:
        {
            weaponMesh = ar15Mesh;
            meshOffset = FVector(-15.f, 0.f, 0.f);
            break;
        }
        case EWeapon::EW_ASVAL:
        {
            weaponMesh = kaValMesh;
            meshOffset = FVector(-15.f, 0.f, 0.f);
            break;
        }
        case EWeapon::EW_SMG11:
        {
            weaponMesh = smg11Mesh;
            meshOffset = FVector(-15.f, 0.f, 0.f);
            break;
        }
        case EWeapon::EW_SUB:
        {
            weaponMesh = ak47uMesh;
            meshOffset = FVector(-15.f, 0.f, 0.f);
            break;
        }
        default:
        {
            weaponMesh = ak47Mesh;
            meshOffset = FVector(-15.f, 0.f, 0.f);
            break;
        }
    
        }
        if (weaponMeshComponent)
        {
            weaponMeshComponent->SetStaticMesh(weaponMesh);
            weaponMeshComponent->SetRelativeLocation(FVector(ForceInitToZero));
            weaponMeshComponent->SetRelativeLocation(meshOffset);
            weaponMeshComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision);
        }
    }

    AShooterCPPGameMode.h

    Code:
    #include "CoreMinimal.h"
    #include "GameFramework/GameModeBase.h"
    #include "PickupBase.h"
    
    #include "ShooterCPPGameMode.generated.h"
    
    
    UCLASS(minimalapi)
    class AShooterCPPGameMode : public AGameModeBase
    {
        GENERATED_BODY()
    
    public:
        AShooterCPPGameMode();
        virtual void BeginPlay() override;
    
    protected:
    
        UFUNCTION(Server, Reliable, WithValidation)
        void SpawnWeaponToWorld(EWeapon weapon, FVector location, FRotator rotation);
    };

    AShooterCPPGameMode.cpp


    Code:
    #include "ShooterCPPGameMode.h"
    #include "ShooterCPPCharacter.h"
    #include "UObject/ConstructorHelpers.h"
    #include "PickupBase.h"
    #include "RiflePickup.h"
    #include "PickupBase.h"
    #include "Engine/World.h"
    
    
    
    AShooterCPPGameMode::AShooterCPPGameMode()
    {
        // set default pawn class to our Blueprinted character
        static ConstructorHelpers::FClassFinder<APawn> PlayerPawnBPClass(TEXT("/Game/ThirdPersonCPP/Blueprints/ThirdPersonCharacter"));
        if (PlayerPawnBPClass.Class != NULL)
        {
            DefaultPawnClass = PlayerPawnBPClass.Class;
        }
    }
    
    void AShooterCPPGameMode::BeginPlay()
    {
        Super::BeginPlay();
    
        UWorld* world = GetWorld();
    
        if (world)
        {
            FVector location = FVector(-1000.f, -1000.f, 200.f);
            FRotator rotation = FRotator::ZeroRotator;
    
            // Spawning a single weapon to the works works on the server, but is not displayed on the client
    
            SpawnWeaponToWorld(EWeapon::EW_AK47, location, rotation);
            ARiflePickup* temp =  (ARiflePickup*) GetWorld()->SpawnActor<APickupBase>(ARiflePickup::StaticClass(), location, rotation);
            temp->Initialize(EWeapon::EW_AK47);
    
        }
    }
    
    bool AShooterCPPGameMode::SpawnWeaponToWorld_Validate(EWeapon weapon, FVector location, FRotator rotation)
    {
        return true;    
    }
    
    void AShooterCPPGameMode::SpawnWeaponToWorld_Implementation(EWeapon weapon, FVector location, FRotator rotation)
    {
        ARiflePickup* temp = (ARiflePickup*)GetWorld()->SpawnActor<APickupBase>(ARiflePickup::StaticClass(), location, rotation);
        bool test = temp->HasAuthority();
        temp->Initialize(EWeapon::EW_AK47);
    }

    So, in my GameMode class, I'm spawning a single pickup. It works perfectly on the server, but will not propigate to the client.

    Can someone please tell me what I'm doing wrong?

    Thanks in advance!


Working...
X