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 
相关推荐
-森屿安年-4 小时前
63. 不同路径 II
c++·算法·动态规划
chase_my_dream4 小时前
Cartographer详细讲解
c++·人工智能·自动驾驶
森G4 小时前
75、服务器源码解析---------云视频服务项目
linux·服务器·网络·c++·qt
碧海蓝天20224 小时前
C++法则24:在标准 C++ 中,没有任何可移植的方式判断指针 T* pt 指向的内存位置是否已经 构造了对象,程序员必须手动跟踪哪些元素已构造。
java·开发语言·c++
江华森5 小时前
TCP/IP 协议栈实战 — 7 个实验详解
网络·tcp/ip·智能路由器
charlie1145141915 小时前
现代C++指南:Lambda,让我们用另一种方式持有函数
开发语言·c++
森G5 小时前
77、线程池原理和实现------服务器源码解析----云视频服务项目
服务器·c++·qt
酉鬼女又兒5 小时前
零基础入门计算机网络运输层:端到端通信核心作用、端口号分类规则、复用分用工作机制及UDP与TCP协议全方位对比详解
网络·网络协议·tcp/ip·计算机网络·考研·udp·php
.千余5 小时前
【C++】模板进阶全解:非类型参数|全特化|偏特化|分离编译完全指南
开发语言·c++·笔记·学习·其他
代码改善世界6 小时前
【C++进阶】C++11:列表初始化、右值引用与移动语义、完美转发全解析
java·开发语言·c++