标签:item span rtu processor eric replicate dex anywhere pen
- UActorComponent 及 Non-UActorComponent 同步
- Non-UActorComponent同步 可以理解为继承 UObject 的类,用来装数据的同时又需要暴露给蓝图调用,且带同步功能。
Actor同步的传送门:ue4-Network相关-变量同步
新建一个组件类 UMyComp
MyComp.h
#pragma once
#include "MyComp.generated.h"
UCLASS(Blueprintable, BlueprintType)
class UMyComp : public UTextRenderComponent
{
GENERATED_BODY()
public:
UMyComp();
UFUNCTION(BlueprintCallable, Category = AMyNetCharacter)
virtual void OnRep_Length();
public:
UPROPERTY(ReplicatedUsing = OnRep_Length, EditAnywhere, BlueprintReadWrite, Category = UMyComp)
int32 Length;
};
MyComp.cpp
#include "MyNet.h"
#include "MyComp.h"
#include "Net/UnrealNetwork.h"
UMyComp::UMyComp() : Super()
{
UE_LOG(LogMyNet, Warning, TEXT("--- UMyComp::UMyComp"));
Length = 789;
bReplicates = true;
}
void UMyComp::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(UMyComp, Length);
}
void UMyComp::OnRep_Length()
{
SetText(FText::FromString(FString::Printf(TEXT("Length:%d"), Length)));
}
组件的同步分为两大类:静态组件 同步 和 动态组件 同步
静态组件:直接在 c++中构造函数中 CreateDefaultSubobject 构造出来的,or 蓝图中直接 Add Comonent 上去的,在实例化 Actor 后就在 Actor 身上的,这种情况下,只要 Actor 是 Replicated 类型的,就自动会在其他客户端同步该 静态组件,无需指定该 静态组件 为 Replicated 类型。只有在该 静态组件 里面有需要同步的变量或者事件时,才需要指定为 Replicated 类型
蓝图
这里新建了一个蓝图类 MyCompBp 继承 UMyComp,再起一个 RepNotify 类型的 Num 变量,在改变时修改展示内容。然后在 Actor 中 Add Componen 挂上去
测试蓝图中的变量是否能同步
c++
在 Actor 的构造函数中创建,在 Actor 的蓝图就可以看见该组件
AMyNetCharacter::AMyNetCharacter()
{
CusComp = CreateDefaultSubobject<UMyComp>(TEXT("CusComp"));
CusComp->SetupAttachment(RootComponent);
//CusComp->SetNetAddressable();
CusComp->SetIsReplicated(true);
}
测试c++中的变量是否能同步
动态组件:游戏运行时中动态实例化出来或删除的组件(必须在服务端上Spawn or Destroy)。必须指定为 Replicated 类型才能同步给所有客户端。
蓝图
蓝图中动态实例化组件接口 Add Component,实例化出来一定要调用 SetIsReplicated 接口,同时 DyCusCompBp 变量也必须是 Replicated 类型
在测试一下变量同步
c++
在actor中写个接口给蓝图调用
UPROPERTY(Replicated, EditAnywhere, BlueprintReadWrite, Category = AMyNetCharacter)
UMyComp* DynamicCusComp22;
UFUNCTION(BlueprintCallable, Category = AMyNetCharacter)
virtual void SpawnMyComp();
void AMyNetCharacter::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
DOREPLIFETIME(AMyNetCharacter, DynamicCusComp22);
}
void AMyNetCharacter::SpawnMyComp()
{
if (DynamicCusComp22)
DynamicCusComp22->DestroyComponent();
DynamicCusComp22 = NewObject<UMyComp>(this, UMyComp::StaticClass());
DynamicCusComp22->RegisterComponent();
FAttachmentTransformRules AttachmentRules(EAttachmentRule::KeepRelative, false);
DynamicCusComp22->AttachToComponent(GetRootComponent(), AttachmentRules);
DynamicCusComp22->SetRelativeLocation(FVector(0.f, 100.f, 50.f));
//DynamicCusComp22->SetNetAddressable(); //绝逼不能调这个,否则所有客户端断线
DynamicCusComp22->SetIsReplicated(true);
}
Manually marked (via UActorComponent::SetNetAddressable)
,实测不行,有待研究源码。会报错:Stably named sub-object not found. Component
在测试一下变量同步
新建个继承 UObject 的数据类 UMyItem
MyItem.h
#pragma once
#include "MyItem.generated.h"
UCLASS(Blueprintable, BlueprintType)
class UMyItem : public UObject
{
GENERATED_BODY()
public:
UMyItem();
virtual ~UMyItem();
public:
UFUNCTION()
virtual void OnRep_Count();
virtual bool IsSupportedForNetworking() const override
{
return true;
}
public:
UPROPERTY(ReplicatedUsing = OnRep_Count, EditAnywhere, BlueprintReadWrite, Category = UMyItem)
int32 Count;
};
MyItem.cpp
#include "MyNet.h"
#include "MyItem.h"
#include "Net/UnrealNetwork.h"
UMyItem::UMyItem() : Super()
{
UE_LOG(LogMyNet, Warning, TEXT("--- UMyItem::UMyItem"));
Count = 32;
}
UMyItem::~UMyItem()
{
UE_LOG(LogMyNet, Warning, TEXT("--- UMyItem::~UMyItem"),);
}
void UMyItem::OnRep_Count()
{
FString msg = FString::Printf(TEXT("--- OnRep_Count Count:%d"), Count);
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, *msg);
}
void UMyItem::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(UMyItem, Count);
}
bReplicates = true;
成员,需要同步的变量加上 Replicated 标记,实现 GetLifetimeReplicatedProps
方法。需要实现 IsSupportedForNetworking
在 Replicated Actor 中重写几个函数
virtual bool ReplicateSubobjects(class UActorChannel *Channel, class FOutBunch *Bunch, FReplicationFlags *RepFlags) override;
//virtual void OnSubobjectCreatedFromReplication(UObject *NewSubobject); 不知道为啥重写这两个函数会造成不能同步,逻辑上看起来没问题,有待探究
//virtual void OnSubobjectDestroyFromReplication(UObject *Subobject);
bool AMyNetCharacter::ReplicateSubobjects(class UActorChannel *Channel, class FOutBunch *Bunch, FReplicationFlags *RepFlags)
{
bool WroteSomething = Super::ReplicateSubobjects(Channel, Bunch, RepFlags);
if (CusObj != nullptr)
{
WroteSomething |= Channel->ReplicateSubobject(CusObj, *Bunch, *RepFlags);
}
return WroteSomething;
}
/*
void AMyNetCharacter::OnSubobjectCreatedFromReplication(UObject *NewSubobject)
{
Super::OnSubobjectCreatedFromReplication(NewSubobject);
FString msg = FString::Printf(TEXT("--- OnSubobjectCreatedFromReplication ClassName:%s"), *NewSubobject->GetClass()->GetName());
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, *msg);
}
void AMyNetCharacter::OnSubobjectDestroyFromReplication(UObject *Subobject)
{
FString msg = FString::Printf(TEXT("--- OnSubobjectDestroyFromReplication ClassName:%s"), *Subobject->GetClass()->GetName());
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, *msg);
Super::OnSubobjectDestroyFromReplication(Subobject);
}
*/
在服务端生产一个对象,然后会同步到所有客户端
UFUNCTION(BlueprintCallable, Category = AMyNetCharacter)
virtual void SpawnMyItem();
void AMyNetCharacter::SpawnMyItem()
{
if (!HasAuthority()) //确保是服务端去new组件
return;
if (CusObj)
CusObj->ConditionalBeginDestroy();
CusObj = NewObject<UMyItem>(this, UMyItem::StaticClass());
}
测试修改一下里面的数据是否能同步到其他客户端
结果:(在Client2中操作)
在 Replicated Actor 中示例化 UMyItem 时会在 所有客户端同步回调
virtual void OnSubobjectCreatedFromReplication(UObject *NewSubobject);
在销毁 Replicated Actor 的时候会会在所有客户端 销毁 UMyItem
virtual void OnSubobjectDestroyFromReplication(UObject *Subobject);
在源码中没有找到 动态销毁UMyItem 的方法,它只有在 Actor 销毁的时候跟着被销毁。所以还不能完全控制(应该是我还找到)。想要完全控制的话可以用 UActorComponent。
标签:item span rtu processor eric replicate dex anywhere pen
原文地址:http://blog.csdn.net/yangxuan0261/article/details/54772711