This translation is community contributed and may not be up to date. We only maintain the English version of the documentation. Read this manual in English
エンジンはユーザーからのすべての入力を取得し、入力フォーカス(input focus)を取得したゲームオブジェクト(game object)内にある、on_input() 関数を実装したスクリプトコンポーネント(script component)と GUI スクリプトコンポーネントにアクション(action)として配信します。このマニュアルでは、入力を取得するための入力バインディング(input binding)の設定方法と、入力に反応するコードの作成方法を説明します。
入力システムは、シンプルで強力な概念をいくつか組み合わせており、ゲームに合った方法で入力を管理できます。

入力バインディングはプロジェクト全体に適用されるテーブルです。デバイスからの入力をスクリプトコンポーネントや GUI スクリプトに配信する前に、名前を付けた アクション へどう変換するかを指定できます。新しい入力バインディングファイルを作成するには、Assets ビュー内の場所を 右クリック し、New... ▸ Input Binding を選択します。エンジンが新しいファイルを使うようにするには、game.project の Game Binding 項目を変更します。

すべての新規プロジェクトテンプレートでは、デフォルトの入力バインディングファイルが自動的に作成されるため、通常は新しいバインディングファイルを作成する必要はありません。デフォルトのファイル名は game.input_binding で、プロジェクトのルートにある input フォルダーにあります。ファイルを ダブルクリック してエディターで開きます。

新しいバインディングを作成するには、該当するトリガーの種類のセクションの下部にある + ボタンをクリックします。各項目には2つのフィールドがあります。
A ボタンをアクション jump にバインドできます。ただし、残念ながらタッチ入力には他の入力と同じアクション名を付けられないという既知のバグがあります。デバイスに対応した5種類の入力トリガー(input trigger)を作成できます。
上記の5種類のトリガーに加えて、Defold は Android と iOS のネイティブアプリケーションで加速度計の入力もサポートしています。game.project ファイルの Input セクションで Use Accelerometer チェックボックスをオンにします。
function on_input(self, action_id, action)
if action.acc_x and action.acc_y and action.acc_z then
-- react to accelerometer data
end
end
スクリプトコンポーネントや GUI スクリプトで入力アクションを受信するには、コンポーネントを持つゲームオブジェクトに acquire_input_focus メッセージを送信します。
-- tell the current game object (".") to acquire input focus
msg.post(".", "acquire_input_focus")
このメッセージは、ゲームオブジェクト内の入力を受け取れるコンポーネント(スクリプトコンポーネント、GUI コンポーネント、コレクションプロキシ(collection proxy))を 入力スタック に追加するようエンジンに指示します。ゲームオブジェクトのコンポーネントは入力スタックの上に置かれ、最後に追加されたコンポーネントがスタックの一番上になります。ゲームオブジェクトに入力を受け取れるコンポーネントが複数ある場合は、すべてがスタックに追加される点に注意してください。

すでに入力フォーカスを取得しているゲームオブジェクトが再度フォーカスを取得すると、そのコンポーネントがスタックの一番上に移動します。
入力アクションは、入力スタックの順序に従って上から下へ配信されます。

スタック上にあり、on_input() 関数を持つコンポーネントでは、そのフレーム内の入力アクションごとに1回、次の引数を指定してその関数が呼び出されます。
selfaction_idactionpressed であったかなど、アクションに関する有用なデータを含むテーブルです。利用可能なアクションのフィールドについて詳しくは、on_input() を参照してください。function on_input(self, action_id, action)
if action_id == hash("left") and action.pressed then
-- move left
local pos = go.get_position()
pos.x = pos.x - 100
go.set_position(pos)
elseif action_id == hash("right") and action.pressed then
-- move right
local pos = go.get_position()
pos.x = pos.x + 100
go.set_position(pos)
end
end
コレクションプロキシを通じて動的に読み込まれる各ゲームワールド(game world)は、それぞれ独自の入力スタックを持ちます。配信されるアクションが読み込まれたワールドの入力スタックに届くには、プロキシコンポーネントがメインワールドの入力スタック上にある必要があります。読み込まれたワールドのスタック上のすべてのコンポーネントを処理してから、メインスタックの下への配信を続けます。

コレクションプロキシコンポーネントを持つゲームオブジェクトに acquire_input_focus を送信し忘れるのは、よくある間違いです。この手順を省略すると、読み込まれたワールドの入力スタック上のどのコンポーネントにも入力が届きません。
入力アクションの受信を停止するには、ゲームオブジェクトに release_input_focus メッセージを送信します。このメッセージは、そのゲームオブジェクトのコンポーネントを入力スタックから取り除きます。
-- tell the current game object (".") to release input focus.
msg.post(".", "release_input_focus")
コンポーネントの on_input() では、アクションをスタックの下へさらに渡すかどうかを制御できます。
on_input() が false を返す場合や、戻り値を省略した場合(この場合は nil が返され、Lua では偽の値として扱われます)、入力アクションは入力スタック上の次のコンポーネントに渡されます。on_input() が true を返す場合、入力は消費されます。入力スタックの下にあるコンポーネントは、その入力を受け取りません。これは すべての 入力スタックに適用される点に注意してください。プロキシで読み込まれたワールドのスタック上のコンポーネントが入力を消費し、メインスタック上のコンポーネントに入力が届かないようにすることもできます。
入力の消費は、ゲームのさまざまな部分の間で入力の受信先を切り替えるシンプルで強力な方法で、多くの場面で役立ちます。たとえば、一時的にゲーム内で入力を受け取る唯一の部分となるポップアップメニューが必要な場合です。

ポーズメニューは最初は非表示(無効)になっており、プレイヤーが HUD の PAUSE 項目に触れると有効になります。
function on_input(self, action_id, action)
if action_id == hash("mouse_press") and action.pressed then
-- Did the player press PAUSE?
local pausenode = gui.get_node("pause")
if gui.pick_node(pausenode, action.x, action.y) then
-- Tell the pause menu to take over.
msg.post("pause_menu", "show")
end
end
end

ポーズメニューの GUI は入力フォーカスを取得して入力を消費し、ポップアップメニューに関係するもの以外の入力を受け付けなくします。
function on_message(self, message_id, message, sender)
if message_id == hash("show") then
-- Show the pause menu.
local node = gui.get_node("pause_menu")
gui.set_enabled(node, true)
-- Acquire input.
msg.post(".", "acquire_input_focus")
end
end
function on_input(self, action_id, action)
if action_id == hash("mouse_press") and action.pressed then
-- do things...
local resumenode = gui.get_node("resume")
if gui.pick_node(resumenode, action.x, action.y) then
-- Hide the pause menu
local node = gui.get_node("pause_menu")
gui.set_enabled(node, false)
-- Release input.
msg.post(".", "release_input_focus")
end
end
-- Consume all input. Anything below us on the input stack
-- will never see input until we release input focus.
return true
end