UObject复制与RPC

UObject复制

一、覆写函数IsSupportedForNetworking 让UObject支持复制

复制代码
virtual bool IsSupportedForNetworking() const override { return true; }

还需要在Actor中重写ReplicateSubobjects让子对象实现复制

复制代码
// 子对象
UCLASS()
class UMagicInventory : public UObject
{
    GENERATED_BODY()

public:
	virtual bool IsSupportedForNetworking() const override { return true; }
	
    UPROPERTY(Replicated)
    TArray<FString> Items;
};

// Actor
UCLASS()
class AMagicBox : public AActor
{
    GENERATED_BODY()

public:
    AMagicBox()
    {
        bReplicates = true; // Actor 开启网络复制
        Inventory = CreateDefaultSubobject<UMagicInventory>(TEXT("Inventory"));
    }

    UPROPERTY()
    UMagicInventory* Inventory;

    virtual bool ReplicateSubobjects(UActorChannel* Channel, FOutBunch* Bunch, FReplicationFlags* RepFlags) override
    {
        bool WroteSomething = Super::ReplicateSubobjects(Channel, Bunch, RepFlags);

        if (Inventory)
        {
            // 将子对象 Inventory 同步到客户端
            WroteSomething |= Channel->ReplicateSubobject(Inventory, *Bunch, *RepFlags);
        }

        return WroteSomething;
    }
};

ReplicateSubobjects实现了将AMagicBox的Inventory变量同步到了客户端

如果 不重写 ReplicateSubobjects:

  • Inventory 指针在客户端是 nullptr
  • UMagicInventory 完全不存在
  • 后面就算 Items 标了 Replicated也毫无意义

同时也要重写IsSupportedForNetworking,如果不返回true,则同样:

  • Inventory 指针在客户端是 nullptr
  • UMagicInventory 完全不存在

还需要注意的是Items的复制是GetLifetimeReplicatedProps处理的 不是ReplicateSubobjects处理的,因此UObject内的变量复制也要写完GetLifetimeReplicatedProps的一整套内容

二、注册子对象列表

是5.7版本的新功能,与ReplicateSubobjects做的事基本相同,但是更简洁,适配Iris复制系统

  • 在 Actor 或 Actor Component 的构造函数中启用:
    bReplicateUsingRegisteredSubObjectList = true;
  • 当你创建或想要复制子对象时,在运行时调用:
    AddReplicatedSubObject(YourSubObject);
  • 当子对象销毁或不再需要复制时,调用:
    RemoveReplicatedSubObject(YourSubObject);

AddReplicatedSubObject可以调用的时机?

"此刻是否已经有 ActorChannel,并且我是在服务器上?"

常用位置:

  • 1.BeginPlay()(服务器端)

    • 最常见
    • 生命周期稳定
    • 网络系统已就绪
  • 2.PostInitializeComponents()(服务器端)

    • 比 BeginPlay 更早
    • 适合组件 / 子对象结构初始化完成后立刻注册
  • 3.任何服务器逻辑函数

    • 例如拾取、生成、绑定能力、打开箱子
    • 只要满足:
      • 对象已存在
      • Actor 已开始复制
  • 4.动态创建子对象之后立刻调用

    复制代码
      Inventory = NewObject<UMagicInventory>(this); 
      AddReplicatedSubObject(Inventory);

注意构造函数,OnRep_函数不能调用AddReplicatedSubObject

三、UObject中使用RPC

覆写以下函数让UObject支持RPC ,注意 UPROPERTY() int TestInt; 类中必须有一个UPROPERTY的属性,否则RPC无法调用!

复制代码
#pragma region UObjectNetworking
public:
	virtual bool IsSupportedForNetworking() const override
	{
		return true;
	}

	virtual int32 GetFunctionCallspace(UFunction* Function, FFrame* Stack)
	{
		int32 Callspace = FunctionCallspace::Local;
		if (UObject* Outer = GetOuter()) Callspace = Outer->GetFunctionCallspace(Function, Stack);
		return Callspace;
	}

	//要有一个UPROPERTY()修饰的变量
	UPROPERTY()
	int TestInt;

	AActor* GetActorOuter() const
	{
		return GetTypedOuter<AActor>();
	}

	virtual bool CallRemoteFunction(UFunction* Function, void* Parms, FOutParmRec* OutParms, FFrame* Stack) override
	{
		AActor* Actor = GetTypedOuter<AActor>();
		if (UNetDriver* NetDriver = Actor->GetNetDriver())
		{
			NetDriver->ProcessRemoteFunction(Actor, Function, Parms, OutParms, Stack, this);
			return true;
		}
		return false;
	}

#pragma endregion 
相关推荐
青果网络_xz2 小时前
IP静态是什么意思?静态IP适用于哪些业务场景?
网络·网络协议·tcp/ip
CoderCodingNo2 小时前
【GESP】C++五级练习(前缀和练习) luogu-P1387 最大正方形
开发语言·c++·算法
编程之路从0到12 小时前
JSI入门指南
前端·c++·react native
知乎的哥廷根数学学派2 小时前
基于多尺度特征提取和注意力自适应动态路由胶囊网络的工业轴承故障诊断算法(Pytorch)
开发语言·网络·人工智能·pytorch·python·算法·机器学习
小李独爱秋2 小时前
计算机网络经典问题透视:电子邮件的安全协议PGP主要都包含哪些措施?
运维·服务器·网络·网络协议·计算机网络·安全
上海云盾安全满满2 小时前
棋牌APP被攻击了要怎么办
网络·安全·游戏
小李独爱秋2 小时前
计算机网络经典问题透视:互联网的网络层安全协议族IPsec都包含哪些主要协议?
运维·服务器·开发语言·网络协议·计算机网络·安全
coderxiaohan3 小时前
【C++】C++11
开发语言·c++
雾岛听蓝3 小时前
C++优选算法 | 双指针篇(一)
开发语言·c++