Why I Can't replicate dynamic component from server to clients?

In this document page https://docs.unrealengine.com/en-US/Gameplay/Networking/Actors/Components/index.html , it said:
“Dynamic components are components spawned on the server at runtime and whose creation and deletion replicate down to clients. They work very much in the same way Actors do. Unlike static components, dynamic components need to replicate to exist on all clients.”

The following is my code snaps:

UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class FPSONLINE_API UAttributesSetComponent : public UActorComponent
{
	GENERATED_BODY()

public:	
	// Sets default values for this component's properties
	UAttributesSetComponent();

protected:
	// Called when the game starts
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;

	/* Property replication */
	void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;


	/* current health */
	UPROPERTY(replicated)
		float CurrentHealth;

	/* current bullets */
	UPROPERTY(replicated)
		int32 CurrentBullets;
};

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

	// Replicate current health
	DOREPLIFETIME(UAttributesSetComponent, CurrentHealth);
	DOREPLIFETIME(UAttributesSetComponent, CurrentBullets);
}

// Projectile class
UCLASS()
class FPSONLINE_API AFPSOnlineProjectile : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AFPSOnlineProjectile();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

	virtual void Destroyed() override;

	UFUNCTION(Category = "Projectile")
		void OnProjectileImpact(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	/* Property replication */
	void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
protected:
	// Sphere component used to test collision
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Components")
		class USphereComponent* SphereComponent;

	// Static Mesh used to provide a visual representation of the object
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
		class UStaticMeshComponent* StaticMesh;

	// Movement
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
		class UProjectileMovementComponent* ProjectileMovementComponent;

	// explodes particles
	UPROPERTY(EditAnywhere, Category = "Effects")
		class UParticleSystem* ExplosionEffect;

	// the damage type used by projectile
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Damage")
		TSubclassOf<class UDamageType> DamageType;

	// the damage dealt by this projectile
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Damage")
		float Damage;

public:
	UPROPERTY(replicated)
		UAttributesSetComponent* AttributesSet;

};

// Sets default values
AFPSOnlineProjectile::AFPSOnlineProjectile()
{
 	// 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;

	// scene components
	SphereComponent = CreateDefaultSubobject<USphereComponent>(TEXT("RootComponent"));
	SphereComponent->InitSphereRadius(37.5f);
	SphereComponent->SetCollisionProfileName(TEXT("BlockAllDynamic"));
	RootComponent = SphereComponent;

	// register hit event
	if (GetLocalRole() == ROLE_Authority)
	{
		SphereComponent->OnComponentHit.AddDynamic(this, &AFPSOnlineProjectile::OnProjectileImpact);
	}

	// mesh
	static ConstructorHelpers::FObjectFinder<UStaticMesh> DefaultMesh(TEXT("/Game/StarterContent/Shapes/Shape_Sphere.Shape_Sphere"));
	StaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
	StaticMesh->SetupAttachment(RootComponent);

	// Set the Static Mesh and its position/scale if we successfully found a mesh asset to use.
	if (DefaultMesh.Succeeded())
	{
		StaticMesh->SetStaticMesh(DefaultMesh.Object);
		StaticMesh->SetRelativeLocation(FVector(0.f, 0.f, -37.5f));
		StaticMesh->SetRelativeScale3D(FVector(0.75f, 0.75f, 0.75f));
	}

	// particles
	static ConstructorHelpers::FObjectFinder<UParticleSystem> DefaultExplosionEffect(TEXT("/Game/StarterContent/Particles/P_Explosion.P_Explosion"));
	if (DefaultExplosionEffect.Succeeded())
	{
		ExplosionEffect = DefaultExplosionEffect.Object;
	}

	// Movement Component
	ProjectileMovementComponent = CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("ProjectileMovement"));
	ProjectileMovementComponent->SetUpdatedComponent(SphereComponent);
	ProjectileMovementComponent->InitialSpeed = 1500.f;
	ProjectileMovementComponent->MaxSpeed = 1500.f;
	ProjectileMovementComponent->bRotationFollowsVelocity = true;
	ProjectileMovementComponent->ProjectileGravityScale = 0.f;

	// Damage
	DamageType = UDamageType::StaticClass();
	Damage = 10.f;
}

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

	// Replicate 
	DOREPLIFETIME(AFPSOnlineProjectile, AttributesSet);
}

// AFPSOnlineCharacter class 
// this function run on server side
void AFPSOnlineCharacter::HandleFire_Implementation()
{
	FVector SpawnLocation = GetActorLocation() + (GetControlRotation().Vector() * 100.f) + GetActorUpVector() * 50.f;
	FRotator SpawnRotation = GetControlRotation();

	FActorSpawnParameters SpawnParameters;
	SpawnParameters.Instigator = GetInstigator();
	SpawnParameters.Owner = this;

	AFPSOnlineProjectile* SpawnedProjectile = ()->SpawnActor<AFPSOnlineProjectile>(SpawnLocation, SpawnRotation, SpawnParameters);

	SpawnedProjectile->AttributesSet = NewObject<UAttributesSetComponent>(SpawnedProjectile, TEXT("ProjectileAttributes"));
	if (SpawnedProjectile->AttributesSet)
	{
		SpawnedProjectile->AttributesSet->SetNetAddressable(); // Make DSO components net addressable
		SpawnedProjectile->AttributesSet->SetIsReplicated(true); // Enable replication by default
		SpawnedProjectile->AttributesSet->RegisterComponentWithWorld(());
	}
}

Now, When I press fire button in game, the HanleFire_Implementation() will run on server, and then a projectile actor is replicated to client, but the class data memeber AttributesSet can’t be replicated to client。

What’s wrong with me? Thanks.

you can copy the question to a notepad++ to reading.

I fixed formatting for you

oh… I got it!

the following function should not be invoked!!! SetNetAddressable() is for DSO or Blueprint Construction. :slight_smile:

SpawnedProjectile->AttributesSet->SetNetAddressable(); // Make DSO components net addressable