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 
相关推荐
luojiezong13 小时前
锐捷一机一网3.0全新发布:打造一张可成长的网络
网络
日取其半万世不竭13 小时前
用 Netdata 实时监控服务器,比 Prometheus + Grafana 轻量得多
linux·服务器·网络·系统架构·负载均衡·zabbix·grafana
2401_8818283213 小时前
交换综合实验报告
网络
d111111111d13 小时前
了解Modbus
网络·笔记·stm32·单片机·嵌入式硬件·学习
Hui_AI72014 小时前
基于RAG的农产品GEO溯源智能问答系统实现
开发语言·网络·人工智能·python·算法·创业创新
charlie11451419114 小时前
通用GUI编程技术——图形渲染实战(三十八)——顶点缓冲与输入布局:GPU的第一个三角形
开发语言·c++·学习·图形渲染·win32
程序员JerrySUN14 小时前
Jetson边缘嵌入式实战课程第二讲:JetPack 和 SDK Manager 是什么
c语言·开发语言·网络·udp·音视频
用户8055336980314 小时前
现代Qt开发教程(新手篇)1.10——进程
c++·qt
忡黑梨14 小时前
eNSP_从直连到BGP全网互通
c语言·网络·数据结构·python·算法·网络安全
海参崴-14 小时前
C++ STL篇 AVL树的模拟实现
开发语言·c++