Unreal Engine 高效数组复制用法详解

文章目录


前言

在 Unreal Engine 中,FFastArraySerializerFFastArraySerializerItem 是用于高效网络复制数组数据的工具类,尤其在需要频繁同步动态数组时(如背包系统、技能列表等场景)。以下通过一个 背包物品同步 的示例详细说明它们的用法。


提示:以下是本篇文章正文内容,下面案例可供参考

一、核心概念

  • FFastArraySerializerItem: 表示数组中的单个元素,需要包含复制标识符 ReplicationID 和 ReplicationKey。
  • FFastArraySerializer: 管理数组的容器类,负责处理网络复制逻辑和变化追踪。

二、实现步骤

2.1 定义 Item 结构体

cpp 复制代码
// 继承自 FFastArraySerializerItem
USTRUCT()
struct FInventoryItem : public FFastArraySerializerItem
{
    GENERATED_BODY()

    UPROPERTY()
    FName ItemID;       // 物品唯一ID

    UPROPERTY()
    int32 Quantity;     // 数量

    UPROPERTY()
    float Durability;   // 耐久度

    // 网络复制标识符(必须实现)
    void PreReplicatedRemove(const struct FInventoryArray& Serializer);
    void PostReplicatedAdd(const struct FInventoryArray& Serializer);
    void PostReplicatedChange(const struct FInventoryArray& Serializer);
};

2.2 定义数组容器

cpp 复制代码
// 继承自 FFastArraySerializer
USTRUCT()
struct FInventoryArray : public FFastArraySerializer
{
    GENERATED_BODY()

    UPROPERTY()
    TArray<FInventoryItem> Items;  // 物品数组

    // 必须重写:标识数组变化
    bool NetDeltaSerialize(FNetDeltaSerializeInfo& DeltaParms) override
    {
        return FFastArraySerializer::FastArrayDeltaSerialize<FInventoryItem, FInventoryArray>(Items, DeltaParms, *this);
    }

    // 示例方法:添加物品
    void AddItem(const FInventoryItem& NewItem)
    {
        Items.Add(NewItem);
        MarkItemDirty(Items.Last()); // 标记为脏数据以触发复制
    }

    // 示例方法:移除物品
    void RemoveItem(int32 Index)
    {
        if (Items.IsValidIndex(Index))
        {
            Items.RemoveAt(Index);
            MarkArrayDirty(); // 标记数组变化
        }
    }
};

2.3 在 Actor 或 Component 中使用

cpp 复制代码
UCLASS()
class AMyCharacter : public ACharacter
{
    GENERATED_BODY()

public:
    // 复制的背包数据
    UPROPERTY(Replicated)
    FInventoryArray Inventory;

    // 注册复制属性
    virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override
    {
        Super::GetLifetimeReplicatedProps(OutLifetimeProps);
        DOREPLIFETIME(AMyCharacter, Inventory);
    }

    // 服务器端添加物品
    UFUNCTION(Server, Reliable)
    void Server_AddItem(FName ItemID, int32 Quantity);
    {
        FInventoryItem NewItem;
        NewItem.ItemID = ItemID;
        NewItem.Quantity = Quantity;
        NewItem.Durability = 100.f;
        Inventory.AddItem(NewItem);
    }
};

三、关键方法说明

3.1 MarkItemDirty()

  • 作用: 标记单个 Item 为"脏数据",触发网络复制。

  • 使用场景: 修改 Item 属性后调用,如:

cpp 复制代码
void ChangeItemQuantity(int32 Index, int32 NewQuantity)
{
    if (Inventory.Items.IsValidIndex(Index))
    {
        Inventory.Items[Index].Quantity = NewQuantity;
        Inventory.MarkItemDirty(Inventory.Items[Index]);
    }
}

3.2 MarkArrayDirty()

  • 作用: 标记整个数组变化(如添加/删除元素)。

  • 自动调用: 通过 AddItem() 或 RemoveItem() 间接调用。

四、回调函数处理

FInventoryItem 中实现复制回调,响应数据变化:

cpp 复制代码
void FInventoryItem::PostReplicatedAdd(const FInventoryArray& Serializer)
{
    // 客户端新增物品时触发(如更新UI)
    UMyUIWidget::Get()->RefreshInventory();
}

void FInventoryItem::PostReplicatedChange(const FInventoryArray& Serializer)
{
    // 客户端物品属性变化时触发(如更新数量显示)
    UMyUIWidget::Get()->UpdateItemDisplay(ItemID);
}

void FInventoryItem::PreReplicatedRemove(const FInventoryArray& Serializer)
{
    // 客户端移除物品前触发(如播放消失动画)
    UMyUIWidget::Get()->RemoveItemDisplay(ItemID);
}

五、网络复制流程

  1. 服务器修改数据 :调用 AddItem()RemoveItem() 或直接修改 Item 属性后标记脏数据。

  2. 引擎自动同步 :通过 NetDeltaSerialize 增量复制变化到客户端。

  3. 客户端触发回调 :根据操作类型(Add/Change/Remove)执行 PostReplicatedAdd 等函数。

六、注意事项

  • 仅在服务器修改数据 :客户端应通过 RPC(如 Server_AddItem)请求修改。

  • 避免频繁操作 :批量操作后调用一次 MarkArrayDirty() 减少带宽。

  • 自定义序列化 :如需优化,可重写 FInventoryItem::NetSerialize()

通过这种机制,FFastArraySerializer 能高效同步动态数组,适用于需要低延迟和高频率更新的游戏系统。

相关推荐
郑寿昌9 小时前
UE6 AI加速Lumen光线追踪降噪技术解析
人工智能·游戏引擎
晴夏。9 小时前
GAS下的网络同步的全面分析【超级全面】
游戏引擎·ue·gas·网络同步
田鸡_10 小时前
Unity新输入系统(Input System)教学篇
unity·游戏引擎·游戏程序
EQ-雪梨蛋花汤10 小时前
【Unity笔记】Unity 音游模板与免费资源:高效构建节奏游戏开发全指南
笔记·unity·游戏引擎
微莱羽墨10 小时前
零、0基础入门Unity 安装详细教程(2026最新版教程,安装Unity看这一篇就够了!)
unity·游戏引擎·unity安装
nnsix11 小时前
Unity 刚体的 默认力、瞬时力 区别
unity·游戏引擎
nnsix11 小时前
Unity Sprite的 Generate Physics Shape 参数解释
unity·游戏引擎
魔士于安11 小时前
Unity完整小球迷宫项目
前端·unity·游戏引擎·贴图·模型
め.11 小时前
Unity协程的原理
unity·游戏引擎
天人合一peng1 天前
unity 生成标记根据背景色标记变色
unity·游戏引擎