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 
相关推荐
倒头就睡的小比特3 天前
算法竞赛C++常用的STL
c++·算法
weilx12343 天前
C++笔记-文件IO-<fcntl.h>
c++
虎头金猫3 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
Smileyqp沛沛3 天前
前端?C++ ?较大差异基础罗列
c++·基础·前端转c++
C语言小火车3 天前
C/C++ 为什么需要编译器?
开发语言·c++
旖旎夜光3 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wuyk5553 天前
《WiFi 嵌入式物联网开发全套实战》| 第 16 章 ESP32 AP+STA 双模共存原理与工程坑点
网络·stm32·物联网
吞下星星的少年·-·3 天前
C++ 萌新语法入门篇
c++·算法比赛
霍霍的袁3 天前
【C++】map 和 set 的使用 | 从用法到底层
开发语言·c++·学习·visual studio
another heaven3 天前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法