hitomo 2025-04-27 13:15 采纳率: 98.4%
浏览 7
已采纳

UE5 TypeScript如何实现自定义数据结构的序列化与反序列化?

在UE5 TypeScript中如何优雅地实现自定义数据结构的序列化与反序列化? 当创建复杂的游戏逻辑时,我们常需要将自定义数据结构(如角色状态、物品信息等)保存到文件或网络传输中。如何在UE5 TypeScript中设计一个通用的序列化与反序列化方案?例如,对于一个包含嵌套对象和数组的自定义类`MyGameData`,如何确保其所有字段都能被正确转换为JSON格式并还原?此外,在面对循环引用或特定UE5对象类型(如`Vector`或`Rotator`)时,又该如何处理以避免错误或数据丢失?
  • 写回答

1条回答 默认 最新

  • 巨乘佛教 2025-04-27 13:16
    关注

    1. 序列化与反序列化的基础概念

    在UE5 TypeScript中,序列化是将自定义数据结构转换为可存储或传输的格式(如JSON),而反序列化则是从该格式还原为原始数据结构的过程。这在游戏开发中至关重要,尤其是在保存游戏进度、网络同步等场景。

    例如,对于一个简单的类:

    
    class MyGameData {
        playerName: string;
        score: number;
        constructor(playerName: string, score: number) {
            this.playerName = playerName;
            this.score = score;
        }
    }
        

    我们可以直接使用`JSON.stringify`和`JSON.parse`来实现基本的序列化与反序列化:

    
    const data = new MyGameData("Alice", 100);
    const serialized = JSON.stringify(data);
    const deserialized = JSON.parse(serialized);
        

    然而,这种简单方法无法处理嵌套对象、数组或特定类型(如`Vector`)的情况。

    2. 处理嵌套对象与数组

    当数据结构变得更加复杂时,我们需要设计更通用的解决方案。以下是一个改进的示例:

    
    class Item {
        name: string;
        quantity: number;
        constructor(name: string, quantity: number) {
            this.name = name;
            this.quantity = quantity;
        }
    }
    
    class PlayerInventory {
        items: Item[];
        constructor(items: Item[]) {
            this.items = items;
        }
    }
    
    class MyGameData {
        playerName: string;
        inventory: PlayerInventory;
        constructor(playerName: string, inventory: PlayerInventory) {
            this.playerName = playerName;
            this.inventory = inventory;
        }
    
        serialize(): string {
            return JSON.stringify(this, (key, value) => {
                if (value instanceof Item) {
                    return { __type: "Item", ...value };
                }
                return value;
            });
        }
    
        static deserialize(json: string): MyGameData {
            const data = JSON.parse(json, (key, value) => {
                if (value && value.__type === "Item") {
                    return new Item(value.name, value.quantity);
                }
                return value;
            });
            return Object.assign(new MyGameData("", new PlayerInventory([])), data);
        }
    }
        

    通过自定义`serialize`和`deserialize`方法,我们能够优雅地处理嵌套对象和数组。

    3. 特定UE5类型的处理

    UE5中的某些类型(如`Vector`或`Rotator`)需要特殊处理。以下是如何序列化和反序列化`Vector`的示例:

    
    class Vector {
        x: number;
        y: number;
        z: number;
        constructor(x: number, y: number, z: number) {
            this.x = x;
            this.y = y;
            this.z = z;
        }
    }
    
    class MyGameDataWithVector {
        position: Vector;
        constructor(position: Vector) {
            this.position = position;
        }
    
        serialize(): string {
            return JSON.stringify(this, (key, value) => {
                if (value instanceof Vector) {
                    return { __type: "Vector", x: value.x, y: value.y, z: value.z };
                }
                return value;
            });
        }
    
        static deserialize(json: string): MyGameDataWithVector {
            const data = JSON.parse(json, (key, value) => {
                if (value && value.__type === "Vector") {
                    return new Vector(value.x, value.y, value.z);
                }
                return value;
            });
            return Object.assign(new MyGameDataWithVector(new Vector(0, 0, 0)), data);
        }
    }
        

    通过标记类型信息(如`__type`),我们可以确保特定UE5类型的正确转换。

    4. 循环引用的处理

    循环引用会导致序列化失败或生成无效数据。解决方法之一是使用`Map`记录已访问的对象:

    
    function serializeWithCycle(obj: any): string {
        const seen = new WeakSet();
        return JSON.stringify(obj, (key, value) => {
            if (seen.has(value)) {
                return;
            }
            if (typeof value === "object" && value !== null) {
                seen.add(value);
            }
            return value;
        });
    }
        

    此方法可以有效避免循环引用问题。

    5. 流程图说明

    以下是整个序列化与反序列化过程的流程图:

    graph TD A[开始] --> B[检查数据类型] B --> C{是否为对象?} C --是--> D[递归处理子属性] C --否--> E[直接返回值] D --> F{是否为特殊类型?} F --是--> G[转换为JSON兼容格式] F --否--> H[保持原样] G --> I[标记类型信息] H --> I I --> J[返回结果]
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 已采纳回答 10月23日
  • 创建了问题 4月27日