Data synchronization method and apparatus, client, and computer storage medium
Patent Information
- Application Number
- CN202610384664.5
- Authority / Receiving Office
- CN · China
- Patent Type
- Applications(China)
- Current Assignee / Owner
- Filing Date
- 2026-03-26
- Publication Date
- 2026-10-09
AI Technical Summary
当需要同步的游戏对象的数量非常巨大时,穿透调用次数也急剧增加,相应地,穿透开销累积导致严重的性能瓶颈,严重影响游戏逻辑热更新的效率
本发明利用采用脚本语言的脚本端预先创建地址连续的存储空间,利用采用编译型编程语言的执行端预先为存储空间创建访问器,执行端根据访问器获取目标数据在存储空间中的存储地址,再根据存储地址从存储空间中读取目标数据,以实现目标数据在脚本端和执行端之间的同步,由于访问器的内存结构与存储空间的存储结构一致、且与存储空间的地址绑定,由此执行端能够直接访问脚本端创建的存储空间,避免了采用穿透调用机制导致的性能瓶颈,提高了游戏逻辑热更新的效率。
Smart Images

Figure CN122884901A_ABST
Abstract
Description
Technical Field
[0001] This invention relates to the field of computer game technology, and more specifically, to a data synchronization method, apparatus, client, and computer storage medium. Background Technology
[0002] In the development of client-side games based on the Unity engine, Lua scripting language is commonly used as the carrier of upper-level business logic to support hot updates and rapid iterations of game logic, while high-performance modules such as underlying rendering, physics, and ECS (Entity-Component-System) system are implemented in C# (managed code) or native C++.
[0003] Data exchange between Lua and C# relies on the bridging layer's call mechanism. Each call involves: (1) pushing / popping Lua virtual machine stack frames; (2) boxing / unboxing Lua value types to C# managed types; (3) Marshal copying from C# managed memory to unmanaged memory; and (4) accumulating GC (garbage collection) pressure. When the number of game objects requiring synchronization is enormous, the number of calls increases dramatically. Consequently, the accumulated overhead of bridging leads to a severe performance bottleneck, significantly impacting the efficiency of hot updates to game logic. Summary of the Invention
[0004] The purpose of this invention is to provide a data synchronization method, apparatus, client, and computer storage medium.
[0005] The embodiments of the present invention can be implemented as follows: In a first aspect, the present invention provides a data synchronization method applied to a client, the client comprising a script end and an execution end, the script end employing a scripting programming language, the execution end employing a compiled programming language, the script end having pre-created contiguous storage space, the method comprising: The execution terminal obtains an accessor that has been pre-created for the storage space. The memory structure of the accessor is consistent with the storage structure of the storage space and is bound to the address of the storage space. The execution terminal obtains the storage address of the target data in the storage space according to the accessor; The execution end accesses the target data according to the storage address to achieve synchronization of the target data between the script end and the execution end.
[0006] In an optional implementation, the step of the execution terminal accessing the target data according to the storage address to achieve synchronization of the target data between the script terminal and the execution terminal includes: When the target data is an attribute of a game object, the execution end reads the attribute that the script end has pre-written into the storage space from the storage space according to the storage address, so as to realize the synchronization of the attribute from the script end to the execution end; When the target data is the processing result of the execution end, the execution end writes the processing result into the storage space according to the storage address, so as to realize the synchronization of the processing result from the execution end to the script end.
[0007] In an optional implementation, there are multiple target data sets, and the step of obtaining the storage address of the target data in the storage space according to a pre-created accessor by the execution terminal includes: The script creates a corresponding contiguous storage space for each target data according to the preset quantity and the data type of each target data, so as to store the preset quantity of each target data in the same storage space; The execution end creates a corresponding accessor for each of the storage spaces, and the storage structure of each storage space is consistent with the memory structure of the corresponding accessor. The execution terminal binds each accessor to the address of the corresponding storage space.
[0008] In an optional implementation, there are multiple target data, each target data includes the same attribute of multiple game objects, and the execution end concurrently schedules multiple worker threads, each of the worker threads is used to perform the reading operation of each attribute of each of the multiple game objects; The step of the execution terminal obtaining the storage address of the target data in the storage space according to the pre-created accessor includes: The execution end runs each worker thread and obtains the storage address of each attribute of the corresponding game object in the storage space according to the accessor of the storage space storing each attribute of the corresponding game object; The step of the execution terminal accessing the target data according to the storage address includes: The execution end runs each worker thread, and reads each attribute of multiple game objects at once according to the storage address of each attribute of the corresponding game object in the storage space.
[0009] In an optional implementation, each game object has an index, and the execution terminal runs each worker thread. The step of obtaining the storage address of each attribute of the corresponding game object in the storage space according to the accessor of the storage space storing each attribute of the corresponding game object includes: The execution end runs each working thread to obtain the starting address and data tag unit of the storage space of each attribute of the corresponding game object from the memory structure of the accessor of the storage space of each attribute of the corresponding game object; Based on the index of each game object, the starting address of the storage space of each attribute, and the data tag unit, the storage address of each attribute of each game object in the storage space is obtained.
[0010] In an optional implementation, the client pre-stores a global registry, which stores the serial number of each attribute and the access pointer of the accessor of the storage space of the corresponding attribute. Before the step of obtaining the storage address of each attribute of a game object in the storage space according to the accessor of the storage space storing each attribute of the game object, the execution terminal runs each worker thread, including: Based on the sequence number of each attribute of the game object corresponding to each worker thread, the access pointer corresponding to the sequence number is obtained from the global registry, and the accessor of the storage space of the corresponding attribute is obtained based on the access pointer.
[0011] In an optional implementation, the target data includes attributes of multiple game objects. After the step of the execution terminal reading the attributes pre-written into the storage space by the script terminal from the storage space according to the storage address, the method includes: When the attribute is a basic attribute, the execution terminal will store the basic attribute of each game object read into a preset buffer. The basic attribute represents the entity identity information of the corresponding game object. When the attribute is a motion attribute, the execution terminal will store the motion attribute of each game object it reads into a preset component.
[0012] Secondly, the present invention provides a data synchronization device applied to a client. The device includes a scripting end and an execution end. The scripting end uses a scripting programming language, and the execution end uses a compiled programming language. The scripting end has pre-created a contiguous storage space, and the execution end is used for: Obtain an accessor that has been pre-created for the storage space, the memory structure of which is consistent with the storage structure of the storage space and is bound to the address of the storage space; Obtain the storage address of the target data in the storage space according to the accessor; The target data is accessed according to the storage address to achieve synchronization of the target data between the script end and the execution end.
[0013] Thirdly, the present invention provides a client comprising a processor and a memory, the memory being used to store a program, and the processor being used to implement the data synchronization method as described in any of the foregoing embodiments when executing the program.
[0014] Fourthly, the present invention provides a computer storage medium having a computer program stored thereon, which, when executed by a processor, implements the data synchronization method as described in any of the foregoing embodiments.
[0015] Compared with the prior art, the present invention has the following beneficial effects: This invention utilizes a scripting language-based scripting end to pre-create contiguous storage space, and an execution end using a compiled programming language to pre-create accessors for the storage space. The execution end obtains the storage address of the target data in the storage space based on the accessor, and then reads the target data from the storage space based on the storage address, thereby achieving synchronization of the target data between the scripting end and the execution end. Since the memory structure of the accessor is consistent with the storage structure of the storage space and is bound to the address of the storage space, the execution end can directly access the storage space created by the scripting end, avoiding the performance bottleneck caused by the penetration call mechanism and improving the efficiency of hot updates of game logic. Attached Figure Description
[0016] To more clearly illustrate the technical solutions of the embodiments of the present invention, the accompanying drawings used in the embodiments will be briefly introduced below. It should be understood that the following drawings only show some embodiments of the present invention and should not be regarded as a limitation on the scope. For those skilled in the art, other related drawings can be obtained based on these drawings without creative effort.
[0017] Figure 1 This is an example diagram illustrating an application scenario provided in this embodiment.
[0018] Figure 2 This is a block diagram of the client provided in this embodiment.
[0019] Figure 3 This is a flowchart illustrating the data synchronization method provided in this embodiment.
[0020] Figure 4 Example diagram of storage space and accessor provided in this embodiment.
[0021] Figure 5 This is a storage example diagram of the basic attributes and motion attributes of the game object provided in this embodiment.
[0022] Figure 6 A block diagram example of the data synchronization device provided in this embodiment. Figure 1 .
[0023] Figure 7 A block diagram example of the data synchronization device provided in this embodiment. Figure 2 .
[0024] Icons: 10-Client; 11-Processor; 12-Memory; 13-Bus; 20-Server; 100-Data Synchronization Device; 110-Script End; 120-Execution End. Detailed Implementation
[0025] To make the objectives, technical solutions, and advantages of the embodiments of the present invention clearer, the technical solutions of the embodiments of the present invention will be clearly and completely described below with reference to the accompanying drawings. Obviously, the described embodiments are only some embodiments of the present invention, and not all embodiments. The components of the embodiments of the present invention described and shown in the accompanying drawings can generally be arranged and designed in various different configurations.
[0026] Therefore, the following detailed description of the embodiments of the invention provided in the accompanying drawings is not intended to limit the scope of the claimed invention, but merely to illustrate selected embodiments of the invention. All other embodiments obtained by those skilled in the art based on the embodiments of the invention without inventive effort are within the scope of protection of the invention.
[0027] It should be noted that similar labels and letters in the following figures indicate similar items. Therefore, once an item is defined in one figure, it does not need to be further defined and explained in subsequent figures.
[0028] In the description of this invention, it should be noted that if terms such as "upper," "lower," "inner," or "outer" are used to indicate the orientation or positional relationship based on the orientation or positional relationship shown in the accompanying drawings, or the orientation or positional relationship in which the product of this invention is usually placed, they are only for the convenience of describing this invention and simplifying the description, and do not indicate or imply that the device or element referred to must have a specific orientation, or be constructed and operated in a specific orientation, and therefore should not be construed as a limitation of this invention.
[0029] Furthermore, the terms "first" and "second" are used only to distinguish descriptions and should not be interpreted as indicating or implying relative importance.
[0030] It should be noted that, where there is no conflict, the features in the embodiments of the present invention can be combined with each other.
[0031] Please refer to Figure 1 , Figure 1 This is an example diagram illustrating an application scenario provided in this embodiment. Figure 1Client 10 and server 20 communicate with each other. In the game development application scenario, client 10 runs an executable program developed and deployed based on Unity3D. Unity3D includes an editor and a runtime. The editor is the visual development environment used during the development phase, while the runtime is the environment in which the game actually runs, responsible for executing the compiled code and logic. The runtime includes three main technical components: Lua VM, DOTS ECS, and Burst Compiler. Lua VM is a lightweight, extensible Lua 5.3 interpreter runtime subsystem, loaded as a native module of Unity Player, used to interpret and execute Lua scripts written in the Lua scripting language. DOTS ECS is a data-oriented, high-performance runtime architecture, mainly including entities, components, and systems. One entity corresponds to one game object, components are pure data containers, and the system is responsible for batch processing entities with specific component combinations. The core mechanism of System execution is the Job System, and the Job System code is written in the C# programming language. Burst Compiler is an integrated, dedicated AOT (Ahead-of-Time) compiler that compiles C# System code marked `[BurstCompile]` into highly optimized native machine code (x86_64 / ARM64) at Unity Player startup (or initial scheduling), instead of IL (Intermediate Language) intermediate code. Lua scripting language is one of the scripting programming languages in this embodiment, C# programming language is one of the compiled programming languages in this embodiment, LuaVM is a specific example of the scripting side in this embodiment, and the C# side (including the ECS system and Job System) is a specific example of the execution side in this embodiment.
[0032] It should be noted that the compiled programming language in this embodiment includes languages that can be compiled into native machine code by an AOT compiler.
[0033] Client 10 can be a game player's computer, mobile phone, game console, etc. Server 20 is an external network service system that provides entity status data to client 10, such as a backend game server, a local virtual machine or host used for testing, etc. Server 20 can package and send the entity data of game objects to client 10 according to an agreed format.
[0034] The script side of client 10 pre-creates a contiguous storage space, and the execution side pre-creates an accessor with the same memory structure as the storage space. The execution side can directly access the storage space through the accessor. The script side can store entity data sent by server 20 into the storage space, and the execution side accesses the entity data in the storage space through the accessor, thereby achieving synchronization of entity data from the script side to the execution side. Conversely, the execution side writes the processing result to the storage space through the accessor, and the script side reads the processing result from the storage space, thereby achieving synchronization of processing results from the execution side to the script side. In this way, the penetration call mechanism can be bypassed, improving the efficiency of data synchronization between the two, and thus improving the efficiency of hot updates of game logic.
[0035] Please refer to Figure 2 , Figure 2 This is a block diagram of the client provided in this embodiment. The client 10 implements the data synchronization method in this embodiment. Figure 2 In the client 10, there are a processor 11, a memory 12 and a bus 13, and the processor 11 and the memory 12 are connected through the bus 13.
[0036] The processor 11 can be an integrated circuit chip with signal processing capabilities. In implementation, each step of the data synchronization method in this embodiment can be completed by the integrated logic circuitry in the processor 11 or by software instructions. The processor 11 can be a general-purpose processor, including a CPU (Central Processing Unit), NP (Network Processor), GPU (Graphics Processing Unit), etc.; it can also be a DSP (Digital Signal Processor), ASIC (Application Specific Integrated Circuit), FPGA (Field Programmable Logic Gate Array), or other programmable logic devices, discrete gate or transistor logic devices, or discrete hardware components.
[0037] The memory 12 is used to store the program that implements the data synchronization method. The program can be a software function module stored in the memory 12 in the form of software or firmware or embedded in the OS (Operating System) of the client 10.
[0038] After receiving the execution instruction, the processor 11 executes the program to implement the data synchronization method of this embodiment.
[0039] based on Figure 1 and Figure 2 This embodiment also provides applications for Figure 1 and Figure 2 For client-side data synchronization methods, please refer to [link / reference]. Figure 3 , Figure 3 This is a flowchart illustrating the data synchronization method provided in this embodiment. The method includes the following steps: In step S101, the execution end obtains an accessor that was previously created for the storage space. The memory structure of the accessor is consistent with the storage structure of the storage space and is bound to the address of the storage space.
[0040] In this embodiment, the storage space is a pre-created, contiguous memory space on the script side. Taking Lua as the script side as an example, the storage space can be a Lua array created by the Lua side, and the underlying storage of the Lua array can be an array allocated by the C language. To ensure the contiguous address of the Lua array and prevent data from overflowing from the array part to the hash part due to nil holes in Lua, thus disrupting the address contiguousness of the Lua array, the Lua array needs to be created in a pre-allocated manner and filled with preset initial values after creation. It should be noted that the above-described method of creating storage space using an array is only one implementation method on the Lua side. In fact, depending on the scripting language used on the script side, contiguous memory space can also be allocated using the space allocation method provided by the scripting language.
[0041] In this embodiment, the accessor is a predefined memory structure on the execution side, whose memory structure is consistent with the storage structure of the storage space. The field layout, byte alignment, and data type definition of this memory structure completely correspond to the memory area where the script actually stores the data in the storage space. The consistency between the accessor's memory structure and the storage structure of the storage space means that the order of the fields, the number of bytes occupied, and the type precision in the accessor strictly reflect the actual organization of the data in the storage space. Binding the accessor to the address of the storage space allows the pointer members inside the structure used to locate data to be set to point to the starting address of the storage space, thereby establishing a static mapping relationship between the two.
[0042] Taking a script with Lua as the scripting language and a C# execution language as the execution language as an example, the accessor can include the following fields: LuaTTable: The underlying structure of the Lua Table in the Lua side, including array pointer and array length; LuaTValue: The underlying structure of Lua values in the Lua side, including the UnionValue union and the type tag tt; UnionValue: A union of Lua values in the Lua context, including integer n, floating-point f, GC (Garbage Collector) object gc, boolean b, etc.
[0043] The specific binding implementation method can be as follows: the internal table pointer of each Lua array is passed to the C# side through the bridge interface (BindLuaTablePtrToCSharp), and the C# side creates the corresponding accessor (LuaArrayVisitor) and binds it to the array header address pointer of the internal table of the Lua array, thereby completing the pointer registration from the Lua script side to the C# side.
[0044] In step S102, the execution end obtains the storage address of the target data in the storage space according to the accessor.
[0045] In this embodiment, the target data can be entity data of the game object that needs to be updated, such as attribute data, sent from the server to the client. Taking the script client as the Lua client as an example, the Lua client can have a dedicated entity manager (WorldEntityMgr) to write the attribute data of each entity into the corresponding attribute array according to predefined indexing rules.
[0046] In this embodiment, when the execution end needs to read target data, the storage address of the target data can be determined by the starting address of the storage space and the linear byte offset of the target data in the storage space. The linear byte offset can be determined by arithmetic operations using the index and data type of the target data. For example, when the index of the target data is 'index', the data type is a single-element type, and the starting address of the storage space is 'tablePtr->array', then the storage address of the target data can be represented as (tablePtr->array) + index.
[0047] In step S103, the execution end accesses the target data according to the storage address to achieve synchronization of the target data between the script end and the execution end.
[0048] In this embodiment, the execution end can use pointer-based methods to forcibly cast the storage address to a pointer of the corresponding data type and directly read or write the memory unit at that address. Taking the accessor structure described above as an example, when the index of the target data is 'index', the data type is a single-element type, and the starting address of the storage space is 'tablePtr->array', the execution end can use unsafe pointer-based methods to forcibly cast the storage address to a pointer of the corresponding data type (LuaTValue). (tablePtr->array)+index, directly access the target data.
[0049] In this embodiment, the target data is synchronized between the script end and the execution end. This can be either the target data is written to the script end and read by the execution end, or the target data is written to the execution end and read by the script end.
[0050] The method provided in this embodiment, since the memory structure of the accessor is consistent with the storage structure of the storage space and is bound to the address of the storage space, allows the execution end to directly access the storage space created by the script end, avoiding the performance bottleneck caused by the penetration call mechanism and improving the efficiency of hot update of game logic.
[0051] In an optional implementation, in order to achieve synchronization of target data in different directions between the script end and the execution end for different target data, this embodiment also provides a processing method: When the target data is an attribute of a game object, the execution end reads the attribute that the script end has pre-written into the storage space from the storage space according to the storage address, so as to realize the synchronization of the attribute from the script end to the execution end; When the target data is the processing result of the execution end, the execution end writes the processing result into the storage space according to the storage address, so as to realize the synchronization of the processing result from the execution end to the script end.
[0052] In this embodiment, the attributes of a game object may include motion-related data such as the game object's position, speed, state, and skills, as well as basic information such as the game object's identifier, configuration table identifier, entity type, and appearance type. The processing results from the execution end include, but are not limited to, visual interpolation position and radar search results.
[0053] In this embodiment, to maintain unidirectional data dependency and avoid read / write contention, script-side writing and execution-side reading, and execution-side writing and script-side reading, can be implemented using different storage spaces to achieve a closed loop of bidirectional data flow. For example, target data such as game object attributes are transferred from the Lua end to the C# end using a dedicated input array, and the processing results from the execution end are transferred from the C# end to the Lua end using a dedicated output array.
[0054] In an optional implementation, when a game frame includes multiple game objects, and each game object includes multiple attributes, each attribute corresponds to a target data. Therefore, a storage space needs to be created for each target data to store the same attribute of all game objects in the same storage space. This embodiment provides an implementation method: First, the script creates a corresponding contiguous storage space for each target data according to the preset quantity and the data type of each target data, so as to store the preset quantity of each target data in the same storage space; In this embodiment, the preset quantity can be the total number of game objects in a game frame or the estimated maximum number of game objects. The target data consists of the same type of attribute for multiple game objects; for example, target data 1 includes the position attributes of multiple game objects, and target data 2 includes the speed attributes of multiple game objects. This data layout, which splits each attribute of a game object into independent storage spaces—for example, an array for each attribute, rather than a SoA (Structure of Arrays) structure for each game object—is very suitable for CPU cache line access and is naturally adapted to SIMD (Single Instruction, Multiple Data) vectorized processing.
[0055] Secondly, the execution side creates a corresponding accessor for each storage space, and the storage structure of each storage space is consistent with the memory structure of the corresponding accessor. Finally, the execution end binds each accessor to the address of the corresponding storage space.
[0056] To illustrate the relationship between storage space and accessors more clearly, please refer to [link / reference]. Figure 4 , Figure 4 Example diagram of storage space and accessor provided in this embodiment. Figure 4 In this system, each entity corresponds to a game object. The entity ID, position attribute, and speed attribute each correspond to a different array. Each array corresponds to an accessor, and each accessor is bound to the starting address of its respective array. In array `array1`, 1 and 2 are the IDs of entity 1 and entity 2, respectively. The other two elements, 0, indicate that the entity has not yet been created and is reserved. The first field of the accessor corresponding to `array1` stores the starting address of the `array1` array. Therefore, the starting address of the storage space of `array1` can be directly located through this accessor. The other arrays `array2` and `array3` are similar and will not be described further. Figure 4 The diagram shows that the position and velocity attributes are stored in two different arrays, array2 and array3, respectively. In array2, a1 and a2 represent the positions of entity 1 and entity 2, respectively, and in array3, b1 and b2 represent the velocity attributes of entity 1 and entity 2, respectively. The remaining elements in array2 and array3 that are 0 are reserved for entities that have not yet been created.
[0057] It should also be noted that, in order to facilitate the management of all accessors in the same pair, after creating the accessor and binding it to the corresponding array address, Figure 4The system also introduces a global registry to manage all accessors according to their key values, so that when needed, the corresponding accessor can be directly obtained through the global registry, and then the data in the corresponding array can be accessed based on the accessor.
[0058] In an optional implementation, when there are multiple target data, and each target data includes the same attribute of multiple game objects, in order to improve the attribute reading efficiency, this embodiment also provides an implementation method of concurrent reading by multiple worker threads. In this method, the execution end concurrently schedules multiple worker threads, and each worker thread is used to perform the reading operation of each attribute of each game object in the multiple game objects. The specific implementation method can be: The execution end runs each worker thread and obtains the storage address of each attribute of the corresponding game object in the storage space according to the accessor of the storage space storing each attribute of the corresponding game object; The execution end runs each worker thread, which reads each attribute of multiple game objects at once based on the storage address of each attribute of the corresponding game object in the storage space.
[0059] In this embodiment, one worker thread can be responsible for reading each attribute of each game object from multiple game objects, and each worker thread is responsible for different game objects. As one implementation, IJobEntity's JobSystem automatically assigns entities of multiple game objects to different threads. For example, if there are 100 game objects, each with the same three attributes (attribute 1 to attribute 3), the entities of game objects 1-33 are assigned to thread 1, which is responsible for reading attributes 1-3 of each entity in game objects 1-33. The entities of game objects 34-66 are assigned to thread 2, which is responsible for reading attributes 1-3 of each entity in game objects 34-66. The entities of game objects 67-100 are assigned to thread 3, which is responsible for reading attributes 1-3 of each entity in game objects 67-100. When there are a large number of game objects, multiple worker threads can be executed simultaneously on multiple CPU cores to improve the efficiency of concurrently reading each attribute of multiple game objects.
[0060] In an optional implementation, each game object has its own lifecycle. Once a game object is destroyed, it is no longer necessary to update its attributes. To avoid unnecessary data processing, this embodiment only updates the attributes of valid game objects. To quickly identify valid game objects, this embodiment provides the following identification method: The system performs a parallel scan of the storage space containing game object identifiers. If the identifier matches a preset initialization value, the corresponding game object is determined to be either uncreated or destroyed; otherwise, it is considered a valid game object. Taking the identifier as the game object's ID, the storage space as an array, and the preset initialization value as 0 as an example, the accessor scans the ID array in parallel on the Lua side, identifying game objects with IDs not equal to 0 as valid game objects. As a specific scanning method, a parallel job of type IJobParallelFor can be scheduled through the data preprocessing system (LuaDataPreprocessorSystem) to scan the Lua ID array and filter out all valid entities (i.e., game objects with IDs not equal to 0).
[0061] After identifying valid game objects, to quickly determine the storage address of attributes in the storage space, this embodiment sets a unique index for each game object. For any attribute of each game object, the attribute is stored in the corresponding storage space according to the index of each game object. Thus, based on the index of the game object and the starting address of the storage space, the offset of any attribute of each game object in the storage space can be located. One implementation method is as follows: The execution end runs each worker thread to obtain the starting address and data tag unit of the storage space of each attribute of the corresponding game object from the memory structure of the accessor of the storage space of each attribute of the corresponding game object; Based on the index of each game object, the starting address of the storage space for each attribute, and the data tag unit, the storage address of each attribute of each game object in the storage space is obtained.
[0062] In this embodiment, taking the C# side of Unity as the execution end as an example, for any worker thread, array data in Lua VM memory (i.e., storage space) can be directly accessed through an unsafe pointer. When the data type is a single-element type, the storage address of its attribute can be directly located using the index of the game object, such as LuaTTable. The pointer retrieves the address of the array's beginning (i.e., the starting address of the memory space), via (LuaTValue). `(tablePtr->array) + index` performs pointer arithmetic offset to the target element, directly reading the value stored in `LuaTValue.value.n`, where `index` is the index and `tablePtr->array` is the starting address of the storage space. When the data type is a multi-element type (e.g., 3D coordinates), the formula `startIndex = (entityIndex - 1) × structSize + 1` is used to calculate the starting index of the multi-element data, where `entityIndex` is the index of the game object, `structSize` is the size of the multi-element type structure, and `startIndex` is the starting offset position of the multi-element type data in the storage space. `)(tablePtr->array) + startIndex` determines the storage address. When the data type is a variable-length type (such as a Buff list), an additional array of index information can be used to record the starting position and length.
[0063] It should also be noted that, in order to further improve efficiency, the above operations can be compiled into native SIMD instructions (e.g., SSE / AVX) using Burst Compiler, enabling vectorized batch read and write of single instruction multiple data.
[0064] In an optional implementation, to ensure that any worker thread can quickly obtain the accessor for the storage space of each attribute of the corresponding game object, this embodiment pre-stores a global registry on the client side. The global registry stores the sequence number of each attribute and the access pointer of the accessor for the storage space of the corresponding attribute. One way to obtain the accessor is as follows: Based on the ordinal number of each attribute of the game object corresponding to each worker thread, retrieve the access pointer corresponding to the ordinal number from the global registry, and then retrieve the accessor of the storage space of the corresponding attribute based on the access pointer. Please refer again. Figure 4 If the attribute's key is 2, the LuaTTable2 pointer can be directly retrieved from the global registry based on key 2. This pointer points to the accessor of array2, which stores the starting address of array2. Therefore, the starting address of the position attribute array can be obtained. As a specific implementation, in the first frame of multiple game frames, all accessor pointers can be read and written into an ECS singleton component. Subsequent jobs processing subsequent game frames can directly obtain the accessor pointers from the ECS singleton component, avoiding the query overhead caused by querying the global registry every frame.
[0065] In optional implementations, the subsequent processing differs depending on the attribute being read. For example, some attributes are used for updating the entity itself, while others are used for updating the entity's state. This embodiment provides a processing method after reading attributes: When the attribute is a basic attribute, the execution end will store the basic attributes of each game object into a preset buffer. The basic attributes represent the entity identity information of the corresponding game object. When the attribute is a motion attribute, the execution end will store the motion attribute of each game object into a preset component.
[0066] In this embodiment, basic attributes include, but are not limited to, the entity identifier, configuration table ID, entity type (e.g., traveler, pet, building, etc.), appearance type, appearance ID, and player ID of the game object. Motion attributes include, but are not limited to, the position, speed, status, skills, and skill level of the game object.
[0067] In this embodiment, basic attributes are stored in a preset buffer to facilitate the creation, destruction, and update operations that the corresponding game object entity needs to perform based on the basic attributes, so that downstream modules can perform creation, destruction, and update operations based on the decision results.
[0068] In this embodiment, motion attributes are stored in a preset component so that they can be used directly as a data source for subsequent rendering, physics, and animation systems, or as input for Transform, state machine, etc.
[0069] To more intuitively demonstrate the data storage in the preset buffer and preset components, please refer to... Figure 5 , Figure 5 This is an example diagram showing the storage of basic and motion attributes of game objects provided in this embodiment. Figure 5 Taking Unity's C# side as an example, the default buffer is an ECS dynamic buffer, the default component is an ECS component, and the valid game object entity IDs are 123, 456, and 789. The ECS dynamic buffer stores the entity ID, type, and other attributes of each valid game object. The ECS component stores the position, speed, and other attributes of each valid game object.
[0070] To more intuitively demonstrate the performance improvement of the data synchronization method provided in this embodiment, this embodiment compares the traditional cross-language call method with the data synchronization method of this embodiment under the same data volume conditions: taking 1000 world entities, each with at least 30 attributes, as an example, the traditional cross-language call method requires approximately 30,000 cross-language calls per frame, taking approximately 100ms; the data synchronization method of this embodiment, through pointer direct reading + parallel batch processing, reduces the number of cross-language calls to 0, and the data synchronization time is reduced to approximately 1ms, resulting in a performance improvement of approximately two orders of magnitude. Among them, pointer management eliminates the overhead of cross-language calls (approximately a 2x improvement), and the SIMD parallel processing compiled by Burst further brings approximately a 50x improvement, with the two combined achieving an overall performance improvement of over 100x.
[0071] To perform the corresponding steps in the above embodiments and various possible implementations, an implementation method of the data synchronization device 100 is given below. Please refer to... Figure 6 , Figure 6 This is a block diagram of the data synchronization device provided in this embodiment. It should be noted that the basic principle and technical effects of the data synchronization device 100 provided by the present invention are the same as those of the corresponding embodiments described above. For the sake of brevity, some parts of this embodiment are not mentioned.
[0072] The data synchronization device 100 includes a script terminal 110 and an execution terminal 120.
[0073] The execution end 120 is used to: obtain an accessor that has been created in advance for the storage space, the memory structure of the accessor being consistent with the storage structure of the storage space and bound to the address of the storage space; obtain the storage address of the target data in the storage space according to the accessor; and access the target data according to the storage address to achieve synchronization of the target data between the script end and the execution end.
[0074] In an optional implementation, the execution terminal 120 is specifically used to access target data based on the storage address to achieve synchronization of target data between the script terminal and the execution terminal: When the target data is an attribute of a game object, the execution end reads the attribute that the script end has pre-written into the storage space from the storage space according to the storage address, so as to realize the synchronization of the attribute from the script end to the execution end; when the target data is the processing result of the execution end, the execution end writes the processing result into the storage space according to the storage address, so as to realize the synchronization of the processing result from the execution end to the script end.
[0075] In an optional implementation, there are multiple target data sets, and the execution terminal 120 is further used for: The script terminal 110 is used to: create a corresponding contiguous storage space for each target data according to the preset quantity and the data type of each target data, so as to store the preset quantity of each target data in the same storage space.
[0076] The execution terminal 120 is also used to: create a corresponding accessor for each storage space, wherein the storage structure of each storage space is consistent with the memory structure of the corresponding accessor; and bind each accessor to the address of the corresponding storage space.
[0077] In an optional implementation, there are multiple target data, each target data includes the same attribute of multiple game objects, and the execution terminal 120 concurrently schedules multiple worker threads, each worker thread is used to perform the reading operation of each attribute of each of the multiple game objects. In the process of obtaining the storage address of the target data in the storage space based on the pre-created accessor, the execution terminal 120 is also specifically used for: Run each worker thread and, based on the accessor of the storage space storing each attribute of the corresponding game object, obtain the storage address of each attribute of the corresponding game object in the storage space; When the execution terminal 120 accesses the target data according to the storage address, it is further used for: Run each worker thread to read each attribute of multiple game objects at once, based on the storage address of each attribute of the corresponding game object in the storage space.
[0078] In an optional implementation, each game object has an index, and the execution terminal 120 is used to run each worker thread. When obtaining the storage address of each attribute of the corresponding game object in the storage space based on the accessor of the storage space storing each attribute of the corresponding game object, it is further used for: Run each worker thread and retrieve the starting address and data tag unit of the storage space for each attribute of the corresponding game object from the memory structure of the accessor of the storage space for each attribute of the corresponding game object. Based on the index of each game object, the starting address of the storage space for each attribute, and the data tag unit, the storage address of each attribute of each game object in the storage space is obtained.
[0079] In an optional implementation, the client pre-stores a global registry, which stores the serial number of each attribute and the access pointer of the accessor for the storage space of each attribute of the corresponding game object; the execution terminal 120 is also used for: Based on the ordinal number of each attribute of the game object corresponding to each worker thread, the access pointer corresponding to the ordinal number is obtained from the global registry, and the accessor of the storage space of the corresponding attribute is obtained based on the access pointer.
[0080] In an optional implementation, the target data includes attributes of multiple game objects, and the execution terminal 120 is further used for: When the attribute is a basic attribute, the execution end will store the basic attributes of each game object into a preset buffer. The basic attributes represent the entity identity information of the corresponding game object. When the attribute is a motion attribute, the execution end will store the motion attribute of each game object into a preset component.
[0081] Figure 6 This is just one implementation of the data synchronization device 100. In this Unity scenario, this embodiment also provides another implementation method, please refer to... Figure 7 , Figure 7 A block diagram example of the data synchronization device provided in this embodiment. Figure 2 , Figure 7 In addition, the data synchronization device 100 also includes a Lua-side data management module, a memory structure mapping module, an accessor registration management module, a data preprocessing module, a parallel data synchronization module, and a data output write-back module. The main functions of each module are as follows: (1) Lua-side data management module This module belongs to the data source side.
[0082] It is mainly used for: creating pre-allocated contiguous Lua arrays (LuaCSharpArray.New(capacity)) to ensure that the underlying storage is a contiguous C array (the array part of Lua) rather than a hash table; organizing entity data according to the SoA (Structure of Arrays) layout: position array (capacity×3), velocity array, status array, buff array, etc., totaling 30+ independent arrays; receiving entity data sent by the server and writing it to the corresponding index position of the corresponding array; and managing the index mapping of variable-length data (buff, clothing) (startIndex (starting index) + length mode).
[0083] (2) Memory structure mapping module This module belongs to the bridging layer and is used to bridge the gap between the Lua and C# sides.
[0084] Primarily used for: defining memory structures on the C# side that are completely consistent with the internal data structures of the Lua VM. These structures include: LuaTTable: the underlying structure corresponding to the Lua Table (including an array pointer and the length of sizearray); LuaTValue: the underlying structure corresponding to Lua values (including a UnionValue union and a type label tt); UnionValue: the union storage corresponding to Lua values (integer n, floating-point f, GC object gc, boolean b); providing a LuaArrayVisitor accessor, implementing Bind(IntPtr) to bind a C# pointer to the array header address of the Lua table; and implementing direct read / write operations through pointer arithmetic: (LuaTValue... (tablePtr->array) + index. C# uses unsafe pointers to directly access Lua VM memory without any serialization / deserialization or cross-language calls.
[0085] (3) Accessor Registration Management Module This module belongs to the intermediate scheduling layer.
[0086] Primarily used for: maintaining a global accessor registry, managing all LuaArrayVisitor instances indexed by integer keys; defining standardized key namespaces, for example, input array keys = 1~27, output array keys = 1001~1002, and special buffer keys = 9994~9999; the ECS initialization system (LuaMemoryAccessorInitSystem) extracts all accessor pointers from the registry in the first frame and writes them to the ECS singleton component (LuaMemoryAccessorHolderComp) for use by all subsequent jobs. One ECS singleton component initialization, reused across multiple frames, avoids the overhead of querying in each frame.
[0087] (4) Data preprocessing module This module belongs to the entity recognition layer.
[0088] Primarily used for: parallel scanning of the Lua ID array using IJobParallelFor to extract basic information (such as ID, ConfigID, EntityType, etc.) of all valid entities; writing the extracted results to the ECS's EntityInfoLuaDataBufferElement dynamic buffer; and providing downstream entity management systems with decision data for entity creation / destruction / update. Parallel preprocessing quickly filters valid entities, providing an accurate working set for subsequent batch processing.
[0089] (5) Parallel data synchronization module This module belongs to the core computing layer.
[0090] Primarily used for: LuaDataSyncJob([BurstCompile] + IJobEntity): Parallel reading of each entity's position (x, y, z), velocity, state, and other data from a Lua array, and writing it to the corresponding ECS component (ServerDataComp, AdditionalDataComp, etc.); ExternalDataSyncJob: Applying synchronized ECS component data to runtime systems such as Transform and state machines; Using [NativeDisableUnsafePtrRestriction] allows the Burst compiler to directly process Lua pointers; For multi-element data, the index calculation formula is used: startIndex = (entityIndex - 1) × structSize + 1, where entityIndex is the entity index, structSize is the size of the multi-element data structure, and startIndex is the index of the starting element in the multi-element data. Burst Compiler compiles C# Job code into native SIMD instructions (such as SSE / AVX), greatly improving the performance of batch memory reads; IJobEntity automatically distributes entity workloads across multiple threads, achieving data-level parallelism; direct pointer access means that the cost of reading each data element is only one pointer offset + memory read, with no cross-language call overhead.
[0091] It should be noted that this module can include two stages of parallel processing: (1) Preprocessing stage (LuaDataPreprocessorSystem, IJobParallelFor): Parallel scanning of the ID array to identify valid entities; (2) Synchronization stage (LuaDataSyncJob, IJobEntity): Parallel reading of all attributes of each entity.
[0092] (6) Data output write-back module This module belongs to the result feedback layer.
[0093] Primarily used for: LuaDataOutputJob([BurstCompile] + IJobEntity): This method writes the results calculated on the C# ECS side (such as visual interpolation positions, radar search results, etc.) back to the Lua side's output array in parallel. The Lua side can directly read the output array to obtain the C# calculation results without needing a reverse-pathing call. The bidirectional data flow is implemented through two sets of input / output arrays, maintaining unidirectional data dependency and avoiding read / write contention.
[0094] This embodiment provides a computer storage medium on which a computer program is stored. When the computer program is executed by a processor, it implements the data synchronization method as described in this embodiment.
[0095] In summary, this embodiment of the invention provides a data synchronization method, apparatus, client, and computer storage medium. The client includes a script end and an execution end. The script end uses a scripting programming language, and the execution end uses a compiled programming language. The script end has a pre-created storage space with contiguous addresses. The method includes: the execution end obtaining an accessor pre-created for the storage space. The memory structure of the accessor is consistent with the storage structure of the storage space and is bound to the address of the storage space; the execution end obtains the storage address of the target data in the storage space according to the accessor; the execution end accesses the target data according to the storage address to realize the synchronization of the target data between the script end and the execution end. Compared with the prior art, this embodiment has at least the following advantages: (1) Since the memory structure of the accessor is consistent with the storage structure of the storage space and is bound to the address of the storage space, the execution end can directly access the storage space created by the script end, avoiding the performance bottleneck caused by the penetration call mechanism and improving the efficiency of hot update of game logic; (2) Each attribute of the game object entity is split into an independent array (Structure of Arrays), instead of one structure (Array of Structures) for each game object entity. This is therefore friendly to CPU cache lines and naturally adapted to SIMD vectorized processing; (3) Using the UnityDOTS architecture (ECS + Job System + Burst Compiler), data synchronization operations are compiled into Burst native code and executed in parallel on multiple worker threads. The Burst Compiler automatically generates SIMD instructions (SSE / AVX) to achieve vectorized batch read and write of single instruction and multiple data; (4) By using input arrays and output arrays to achieve bidirectional data flow, a unidirectional data dependency relationship is maintained, avoiding read and write contention and memory consistency issues.
[0096] The above descriptions are merely various embodiments of the present invention, but the scope of protection of the present invention is not limited thereto. Any variations or substitutions that can be easily conceived by those skilled in the art within the technical scope disclosed in the present invention should be included within the scope of protection of the present invention. Therefore, the scope of protection of the present invention should be determined by the scope of the claims.
Claims
1. A data synchronization method, characterized in that, Applied to a client, the client includes a script end and an execution end, the script end uses a scripting programming language, the execution end uses a compiled programming language, and the script end has pre-created contiguous storage space. The method includes: The execution terminal obtains an accessor that has been pre-created for the storage space. The memory structure of the accessor is consistent with the storage structure of the storage space and is bound to the address of the storage space. The execution terminal obtains the storage address of the target data in the storage space according to the accessor; The execution end accesses the target data according to the storage address to achieve synchronization of the target data between the script end and the execution end.
2. The method according to claim 1, characterized in that, The steps of the execution end accessing the target data according to the storage address to achieve synchronization of the target data between the script end and the execution end include: When the target data is an attribute of a game object, the execution end reads the attribute that the script end has pre-written into the storage space from the storage space according to the storage address, so as to realize the synchronization of the attribute from the script end to the execution end; When the target data is the processing result of the execution end, the execution end writes the processing result into the storage space according to the storage address, so as to realize the synchronization of the processing result from the execution end to the script end.
3. The method according to claim 1, characterized in that, The target data is multiple, and the step before the execution terminal obtains the storage address of the target data in the storage space according to the pre-created accessor includes: The script creates a corresponding contiguous storage space for each target data according to the preset quantity and the data type of each target data, so as to store the preset quantity of each target data in the same storage space; The execution end creates a corresponding accessor for each of the storage spaces, and the storage structure of each storage space is consistent with the memory structure of the corresponding accessor. The execution terminal binds each accessor to the address of the corresponding storage space.
4. The method according to claim 1, characterized in that, The target data is multiple, and each target data includes the same attribute of multiple game objects. The execution end concurrently schedules multiple worker threads, and each worker thread is used to perform the reading operation of each attribute of each game object in the multiple game objects. The step of the execution terminal obtaining the storage address of the target data in the storage space according to the pre-created accessor includes: The execution end runs each worker thread and obtains the storage address of each attribute of the corresponding game object in the storage space according to the accessor of the storage space storing each attribute of the corresponding game object; The step of the execution terminal accessing the target data according to the storage address includes: The execution end runs each worker thread, and reads each attribute of multiple game objects at once according to the storage address of each attribute of the corresponding game object in the storage space.
5. The method according to claim 4, characterized in that, Each game object has an index, and the execution terminal runs each worker thread. The step of obtaining the storage address of each attribute of the corresponding game object in the storage space according to the accessor of the storage space storing each attribute of the corresponding game object includes: The execution end runs each working thread to obtain the starting address and data tag unit of the storage space of each attribute of the corresponding game object from the memory structure of the accessor of the storage space of each attribute of the corresponding game object; Based on the index of each game object, the starting address of the storage space of each attribute, and the data tag unit, the storage address of each attribute of each game object in the storage space is obtained.
6. The method according to claim 4, characterized in that, The client pre-stores a global registry, which stores the serial number of each attribute and the access pointer of the accessor of the storage space of the corresponding attribute. Before the step of obtaining the storage address of each attribute of a game object in the storage space according to the accessor of the storage space storing each attribute of the game object, the execution terminal runs each worker thread, including: Based on the sequence number of each attribute of the game object corresponding to each worker thread, the access pointer corresponding to the sequence number is obtained from the global registry, and the accessor of the storage space of the corresponding attribute is obtained based on the access pointer.
7. The method according to claim 2, characterized in that, The target data includes attributes of multiple game objects. After the step of the execution terminal reading the attributes pre-written into the storage space by the script terminal from the storage space according to the storage address, the process includes: When the attribute is a basic attribute, the execution terminal will store the basic attribute of each game object read into a preset buffer. The basic attribute represents the entity identity information of the corresponding game object. When the attribute is a motion attribute, the execution terminal will store the motion attribute of each game object it reads into a preset component.
8. A data synchronization device, characterized in that, Applied to a client, the device includes a scripting end and an execution end. The scripting end uses a scripting programming language, and the execution end uses a compiled programming language. The scripting end has pre-created contiguous memory space, and the execution end is used for: Obtain an accessor that has been pre-created for the storage space, the memory structure of which is consistent with the storage structure of the storage space and is bound to the address of the storage space; Obtain the storage address of the target data in the storage space according to the accessor; The target data is accessed according to the storage address to achieve synchronization of the target data between the script end and the execution end.
9. A client, characterized in that, It includes a processor and a memory, the memory being used to store a program, and the processor being used to implement the data synchronization method as described in any one of claims 1-7 when executing the program.
10. A computer storage medium, characterized in that, It stores a computer program that, when executed by a processor, implements the data synchronization method as described in any one of claims 1-7.