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
APickupBase.cpp
ARiflePickup.h (notice this is derived from APickupBase)
ARiflePickup.cpp (notice this is derived from APickupBase)
AShooterCPPGameMode.h
AShooterCPPGameMode.cpp
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!
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!
Comment