Interact with entities during gameplay

This topic provides an overview of the ways you can interact with entities in your project during runtime gameplay.

About component managers, instances and instance IDs

When you work with components, you'll need to understand the difference between component managers, component IDs, and component instances.

Managers typically allow you to interact with individual components either by passing them the instance you want to affect, or by passing them the entity and component ID that identify the instance you want to affect. In the latter case, the component manager will do the lookup for you. For example, you could use DataComponent.set_property ( self, instance, key, value ) to set a property on an instance, or DataComponent.set_property_by_id ( self, entity, id, key, value ) to have the DataComponent look up the instance from the entity and ID you provide.

Using the component ID can sometimes be more convenient. However, if you need to make many calls to the same component manager about the same component instance within a given frame, it's generally better if you look up the component instance yourself, to avoid the (small) overhead of extra lookup calls.

Note: The confusing thing about instances and instance IDs in Lua is that they are both exposed as numbers. You'll have to keep straight what's an ID and what's a reference to an actual instance.

Spawn and destroy an entity

Entities that you place in a level in the Stingray Editor are automatically spawned when you load that level into your game at runtime. These entities are automatically destroyed when the level is unloaded, if they have not already been destroyed.

In addition, you can spawn entities at runtime using the following methods from the EntityManager API:

When you no longer need an entity in your game, you can destroy it by calling EntityManager.destroy(). You can call this function for any entity, regardless of whether you created the entity dynamically by calling the functions above, or whether that entity was spawned automatically when its level was loaded into the game.

Get a list of entities

There are two main ways to get a list of the entities:

Assign and remove components

You can set up an entity in your gameplay code by adding and removing components dynamically, just like you can in the Stingray Editor. You do this through the component manager for the kind of component you want to create or destroy for an entity. You retrieve this component manager from the EntityManager.

For example:

function add_remove_components(entity)
    -- get the component managers
    local data_component_manager = stingray.EntityManager.data_component()
    local xform_component_manager = stingray.EntityManager.transform_component(SimpleProject.world)

    -- assign a new data component
    local id = "My New Data Component"
    local new_component_id = stingray.DataComponent.create(data_component_manager, entity, id)

    -- remove the first instance of a given component on an entity
    local xform_component_ids = { stingray.TransformComponent.instance_ids(xform_component_manager, entity) }
    if next(xform_component_ids) then
        stingray.TransformComponent.destroy(xform_component_manager, entity, xform_component_ids[1])
    end

    -- remove a component instance with a specific ID
    local my_instance = stingray.DataComponent.lookup(data_component_manager, entity, "My New Data Component")
    if my_instance then
        stingray.DataComponent.destroy(data_component_manager, my_instance)
    end
end

Set and retrieve data for a component

You can use Lua to access the components that you have assigned to an entity. Once you have the component instance, the API of the relevant component manager object provides functions to interact with that component.

For example, the following function shows how to use the TransformComponent to get the world space position of an entity from its transform component. It also shows how to use the DataComponent manager API to set a new data value for a custom data component.

function change_component_values(entity)
    -- get the component managers
    local data_component_manager = stingray.EntityManager.data_component()
    local xform_component_manager = stingray.EntityManager.transform_component(SimpleProject.world)

    -- get component values from a transform component.
    -- there can only be one transform component on an entity, so instances() returns a single ID.
    local xform_component_id = stingray.TransformComponent.instances(xform_component_manager, entity)
    if xform_component_id then
        -- get its data values
        local world_matrix = stingray.TransformComponent.world_pose(xform_component_manager, entity)
        -- use the values
        print("Entity's world space transform: " .. tostring(world_matrix))
    end

    -- set new data component values on a data component.
    -- there can be many different data components with different fields, so we
    -- need to iterate through a list of IDs to find the one that has the value we want to set.
    local data_component_ids = { stingray.DataComponent.instances(data_component_manager, entity) }
    for index, data_component_id in ipairs(data_component_ids) do
        -- check that the data component contains the field we want to change...
        local property_value = stingray.DataComponent.get_property(data_component_manager, entity, data_component_id, "custom_numeric_field")
        if property_value then
            -- set the new value
            stingray.DataComponent.set_property(data_component_manager, entity, data_component_id, "custom_numeric_field", 250)
        end
    end
end