Golang新实体组件系统Ark的发布与应用

Golang新实体组件系统Ark的发布与应用 Ark 是一个基于原型的 Go 语言实体组件系统。

它建立在构建我的第一个 Go ECS —— Arche 时所获得的经验之上。

特性

  • 为性能而设计并高度优化。
  • 文档完善、类型安全的 API 以及全面的用户指南。
  • 将实体关系作为一等特性。
  • 用于批量操作的快速批处理。
  • 没有系统。只有查询。使用你自己的结构(或工具)。
  • 世界序列化与反序列化(通过 ark-serde)。

目标

在构建我的第一个 Go ECS —— Arche 时,我学到了很多,是时候重新开始了。与 Arche 相比,Ark 的主要目标是:

  • 更好地支持实体关系。
  • 围绕通用、类型安全的 API 构建。
  • 使其比 Arche(甚至)更快。
  • 通过更好地规划特性,使内部结构更加清晰。

经过 3 周的开发,所有这些目标都已实现。就初始计划而言,Ark 现在功能已经完备。

非常感谢您的反馈,特别是关于 API 和用户指南的反馈!


更多关于Golang新实体组件系统Ark的发布与应用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang新实体组件系统Ark的发布与应用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Ark 看起来是一个很有潜力的 ECS 实现,特别是它强调类型安全和性能。以下是一个简单的示例,展示如何定义组件、创建实体并进行查询:

package main

import (
    "fmt"
    "github.com/mlange-42/ark"
)

// 定义位置组件
type Position struct {
    X, Y float64
}

// 定义速度组件  
type Velocity struct {
    X, Y float64
}

func main() {
    // 创建世界
    world := ark.NewWorld()
    
    // 注册组件类型
    posType := ark.RegisterComponent[Position]()
    velType := ark.RegisterComponent[Velocity]()
    
    // 创建实体并添加组件
    entity := world.NewEntity()
    world.Add(entity, posType, &Position{X: 0, Y: 0})
    world.Add(entity, velType, &Velocity{X: 1, Y: 1})
    
    // 查询所有同时拥有位置和速度组件的实体
    query := world.Query(ark.All(posType, velType))
    
    for query.Next() {
        pos := query.Get(posType).(*Position)
        vel := query.Get(velType).(*Velocity)
        
        // 更新位置
        pos.X += vel.X
        pos.Y += vel.Y
        
        fmt.Printf("实体位置: (%.2f, %.2f)\n", pos.X, pos.Y)
    }
}

对于实体关系的支持,Ark 提供了 Relation 类型:

// 定义关系组件
type Parent struct {
    ark.Relation
}

func main() {
    world := ark.NewWorld()
    
    parentType := ark.RegisterComponent[Parent]()
    posType := ark.RegisterComponent[Position]()
    
    // 创建父实体
    parent := world.NewEntity()
    world.Add(parent, posType, &Position{X: 10, Y: 10})
    
    // 创建子实体并建立关系
    child := world.NewEntity()
    world.Add(child, posType, &Position{X: 0, Y: 0})
    world.Add(child, parentType, &Parent{Target: parent})
    
    // 查询所有有父关系的实体
    query := world.Query(ark.All(posType, parentType))
    
    for query.Next() {
        pos := query.Get(posType).(*Position)
        rel := query.Get(parentType).(*Parent)
        
        // 获取父实体的位置
        parentPos := world.Get(rel.Target, posType).(*Position)
        
        fmt.Printf("子实体位置: (%.2f, %.2f), 父实体位置: (%.2f, %.2f)\n",
            pos.X, pos.Y, parentPos.X, parentPos.Y)
    }
}

批量操作可以通过 Batch 实现:

// 批量创建实体
batch := world.Batch(ark.All(posType, velType))
entities := make([]ark.Entity, 100)

for i := 0; i < 100; i++ {
    entity := batch.NewEntity()
    world.Add(entity, posType, &Position{X: float64(i), Y: float64(i)})
    world.Add(entity, velType, &Velocity{X: 0.5, Y: 0.5})
    entities[i] = entity
}
batch.Commit()

这些示例展示了 Ark 的核心功能。类型安全的 API 确实让代码更加清晰,关系作为一等公民的特性也很实用。性能优化在批量操作时应该会有明显体现。

回到顶部