Skip to content
Simon edited this page Sep 26, 2022 · 6 revisions

In case you need to iterate over entities with a specific component configuration that is not part of a system then this is possible via the family function of a world. A family keeps track of entities with a specific config and allows sorting and iteration over these entities. Family is used internally by an IteratingSystem. You can access it via the family property.

The following example shows how to get a family for entities with a MoveComponent but without a DeadComponent:

fun main() {
    val world = world {}
    val e1 = world.entity {
        it += Move(speed = 70f)
    }
    val e2 = world.entity {
        it += Move(speed = 50f)
        it += Dead()
    }
    val e3 = world.entity {
        it += Move(speed = 30f)
    }

    // get family for entities with a MoveComponent and without a DeadComponent
    val family = world.family { all(Move).none(Dead) }

    // you can sort entities of a family
    family.sort(compareEntityBy(Move))

    // And you can iterate over entities of a family.
    // In this example it will iterate in following order:
    // 1) e3
    // 2) e1
    family.forEach { entity ->
        // family also supports the typical entity extension functions like get, has, configure, ...
        entity.configure {
            // update entity components
        }
    }
}

Families also support FamilyHooks that allow you to react when an entity gets added to, or removed from a family. Such hooks can be created in a similar way you can create ComponentHooks via the world's configuration. Here is an example:

fun main() {
    val world = world {
        families {
            // hook that reacts on entities that have a MoveComponent and do not have a DeadComponent
            val family = family { all(Move).none(Dead) }
            onAdd(family) { entity ->

            }
            onRemove(family) { entity ->

            }
        }
    }

    // this will trigger the 'onAdd' hook
    val entity1 = world.entity {
        it += Move()
    }
    // this will trigger the 'onRemove' hook
    world -= entity1

    // this will NOT trigger any hook because the entity is never part of the family
    val entity2 = world.entity {
        it += Move()
        it += Dead() // <-- that's the reason
    }
    world -= entity2
}
Clone this wiki locally