ゲームプレイ中にエンティティを操作する

このトピックでは、ランタイムのゲームプレイ中にプロジェクト内のエンティティを操作する方法の概要を説明します。

コンポーネント マネージャ、インスタンス、およびインスタンス ID について

コンポーネントを使用する場合は、コンポーネント マネージャ、コンポーネント ID、コンポーネント インスタンスの違いについて理解する必要があります。

マネージャがユーザに対して個々のコンポーネントの操作を許可するには、関連するインスタンスを渡すか、関連するインスタンスを識別するエンティティおよびコンポーネント ID を渡します。マネージャがユーザにエンティティおよびコンポーネント ID を渡した場合、コンポーネント マネージャはユーザをルックアップします。たとえば、ユーザは DataComponent.set_property ( self, instance, key, value ) を使用してインスタンスのプロパティを設定するか、または DataComponent.set_property_by_id ( self, entity, id, key, value ) を使用して自分が指定したエンティティおよび ID からインスタンスを検索するように DataComponent を設定することができます。

コンポーネント ID を使用する方が便利な場合があります。ただし、同じコンポーネント マネージャに、指定したフレーム内の同じコンポーネント インスタンスについての呼び出しを複数回行う必要がある場合は、コンポーネント インスタンスを自分で検索して、追加ルックアップを呼び出す際のオーバーヘッド(少量)を回避する方が、一般には効率的です。

注: Lua のインスタンスとインスタンス ID が紛らわしいのは、両方とも数値として公開される点です。ID の内容と、実際のインスタンスに対する参照の内容を区別する必要があります。

エンティティをスポーンおよび破壊する

Stingray Editor 内のレベルに配置したエンティティは、ランタイムでゲームにそのレベルをロードすると、自動的にスポーンされます。これらのエンティティは、まだ破壊されていない場合、レベルをロード解除するときに自動的に破壊されます。

さらに、EntityManager API から次の方法を使用して、ランタイムでエンティティをスポーンすることもできます。

ゲーム内のエンティティが不要となった場合は、EntityManager.destroy() を呼び出して破壊することができます。この関数は、上記の関数を呼び出すことでエンティティを動的に作成したか、またはレベルがゲームにロードされたときにエンティティが自動的にスポーンされたかどうかに関係なく、任意のエンティティに対して呼び出すことができます。

エンティティのリストを取得する

エンティティのリストを取得するには、主に次の 2 つの方法があります。

コンポーネントを割り当てる、削除する

Stingray Editor で行う場合と同様に、コンポーネントを動的に追加および削除することで、ゲームプレイ コードにエンティティを設定できます。これを実行するには、エンティティに対して作成または破壊するコンポーネントの種類に対応したのコンポーネント マネージャを使用します。EntityManager からこのコンポーネント マネージャを取得します。

たとえば、次のようになります。

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

コンポーネントにデータを設定および取得する

Lua を使用して、エンティティに割り当てたコンポーネントにアクセスすることができます。コンポーネントのインスタンスを取得したら、関連するコンポーネント マネージャ オブジェクトの API が、コンポーネントと対話する関数を提供します。

たとえば、次の関数は、TransformComponent を使用してエンティティのトランスフォーム コンポーネントからエンティティのワールド空間位置を取得する方法を示します。また、DataComponent マネージャ API を使用してカスタム データ コンポーネントに新しいデータ値を設定する方法も示します。

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