メインコンテンツまでスキップ

機体 インプット/アニメーション 設定

警告

この節を始める前に、(機体 3Dモデル・同期設定)を必ず終わらせてください。
もしくは、FDMi - Exampleパッケージ中に含まれるサンプル例を開いて確認して下さい。

ヒント

サンプル機に同様の設定を施してあります。お手元に用意して、参考にしてください。
以下の記事内容は、まず文字は見ず、記事中の図とサンプルをみることをお勧めします。

1.概要

この章では、FDMiにおける「入力」と「出力」、「FDMiData」の設定方法を説明します。

「入力」と「出力」

入力 / Input

VRやキーボード、もしくは機体自体(オートパイロットなど)や同期による、FDMiへの値の変更を、まとめて「入力」と定義します。 入力は、FDMiData(通常はFDMiFloat)に、「変化量(Value)」と「変化したことを示す通知(Event)」を送信します。

出力 / Output

機体の物理やアニメーション・Transformの移動などを指します。 出力には、以下の2通りの動作パターンが挙げられます。

  • Update(), FixedUpdate()毎に動作する
  • FDMiDataが変化した際に、FDMiDataから送信される「変化したことを示す通知(Event)」をもらい、そのタイミングで動作する

FDMiData

FDMiDataは「値(Value)」と「変更イベント(Event)」を管理します。
FDMiDataは「値を保持する」機構、とも言えます。

  • 「値(Value)」: 入力により入力された値を保持します。出力は値の読み取りができます。
  • 「変更イベント(Event)」: 「入力」が値を変化させた際、「出力」から「値が変更した」ことを知らせます。

この設計を行うことで、例えば、一つの入力結果(レバーの操作)を複数の出力に伝えたり、複数の入力結果(例えばVRとキーボード)を一つの入力結果として保持できるようになります。
また、この設計では、ある入力や出力のみのテストの際、仮置きのFDMiDataを用いることで、単機能テストが行いやすくなります。

2 設定方法

以下、例として、ギアレバー及び脚の展開アニメーションを設定します。 今回は、VRのコントローラを上下に動かすと、ギアレバーが動作するように設定します。

2.1 理想状態

  • VR上で、ギアレバーに手を重ね「Grab」を行う
    • ギアレバーの上下動に関するFDMiDataの値が変化する
    • FDMiDataの値に応じ、ギアレバーの3Dモデルが動作する
    • FDMiDataの値に応じ、脚の格納アニメーションが動作する

2.2 初期設定

まず、VRにおける入力を、FDMiが受け取るための設定を行います。

  1. FDMiFingerTrackerの準備

まず、FDMiFingerTrackerが準備できていることを確認します。 シーン中FDMi stack/FDMi Input InWorldManagementの中にL,Rと名前のついたFDMiFingerTrackerのComponentがあることを確認してください。 FDMiFingerTracker

警告

もし存在しない場合、FDMi stackPackages/FDMi - Example/Prefabsから配置してください。 詳細はワールドの設定にあります。

  1. FDMiInputManagerの配置

対象としたい飛行機(FDMiObjectManager)の子に、FDMiInputManagerのComponentが設定されたGameObjectを配置します。 FDMiInputManager

2.3 VRによる入力系の配置

では、VRの入力を配置します。ここで、入力の仕組みを説明します。

  1. FDMiInputZoneを、入力対象と一致する位置に用意します。FDMiInputZoneには、1:1対応でFDMiInputPageが紐づいています。
  2. FDMiInputZoneの付近でコントローラをGrabすると、FDMiInputPageが呼び出されます。 FDMiInputPageは、配下のFDMiInputAddon(今回はFDMiLeverInput)を起動します。
  3. FDMiInputAddonは、そのときの手の位置・回転・ボタンの状態を読み取り、結果をFDMiData(今回はFDMiFloat)に渡します。

入力の流れ

以下、各項目の設定を説明します。

2.3.1 FDMiInputPage

まず、FDMiInputPageを配置します。 Vechicle/Modelの子に配置します。ほかの入力系を設定する事を踏まえ、今回はVechicle/Model/Input/GearLeverに配置しました。 内部の値は後程の操作で自動設定されます。 FDMiInputPage

2.3.2 FDMiInputZone

FDMiInputZoneを設置します。 今回は、(最終的に動作する)ギアレバーに追従させるため、ギアレバーのボーンの子にGameObjectを作成し配置します。 FDMiInputZone

  • 上図の様に、Is Triggerを有効化したCollierと同じGameObjectにFDMiInputZoneを配置します。
  • InputPageに、先程配置したGearLeverFDMiInputPageを設定します。
  • Hilight Objectには、下図の様な手を近づけた際にハイライトとして光らせたいGameObjectを設定します。
    今回の場合、FDMiInputZoneの子にSphereの3Dモデルを配置し、GameObjectをfalseにしています。
    モデルの制作時、レバー毎にGameObjectを分割すると、レバーにHilightをつけられます。 input_hilight

2.3.3 FDMiLeverInput (+ FDMiDataBusTerminal)

次に、レバーによる動作自体を設定していきます。 まず、Vechicle/Model/Input/GearLeverの子に、FDMiDataBusTerminalを配置します。 そして、その子にFDMiLeverInputを配置します。 terminal_lever

FDMiLeverInputLeverOutputにはFDMiFloatが入ります。FDMiFloatFDMiDataの一種で、float値を格納します。
FDMiLeverInputLeverOutputの値を変更するとともに、変更イベントをLeverOutputに発行します。

以下、FDMiLeverInputの各項目を設定していきます。

  • まず、LeverInputのTransformの位置を”レバーの根本”に持ってきてください。 Leverを手で回したり(Rotate)、ひねったり(Twist)する動作の際の、レバーの根本を示します。

  • Control TypeLever Axisを設定します。

    • Pull: 平行移動による入力量を指します。GrabをしながらLever Axisで設定した方向(このTransformの矢印)に手を動かした量を、Lever Outputに加算します。単位は1/mです。

    • Rotate: Transformを原点とした、回転による入力量を指します。現在のTransformをレバーの支点、Lever Axisを回転軸とした回転移動量をLever Outputに加算します。単位は1/°です。

    • Twist: ひねりによる入力量を指します。Grab中のコントローラー自体の回転量から、Lever Axisで設定した軸周りの回転量を取り出し、Lever Outputに加算します。単位は1/°です。

  • multplier,min,maxを設定します。

    • Grabをすると、LeverOutput=Clamp(LeverOutput + (変化量)* multiplier,min,max)の結果をLeverOutputに格納します。
      今回は以下の設定にします。
    • multplier:1/60 60°回転させたら「1」になるよう、を代入します。
    • min: 0
    • max: 1 lever_mul
  • Detents 手を離した際、Detentsに最も近い値にLeverOutputを設定します。
    Detentsに何も設定しなければ、この動作は発生せず、最後に手を離した位置がレバーの位置になります。
    今回は、ギアレバーの結果なので[0,1]を設定しています。

2.3.4 FDMiData(FDMiDataBusTerminalを使用)

最後に、FDMiDataを設定します。入力結果の値を保存するため,FDMiLeverInputLeverOutputFDMiFloatを配置します。

ここで、そのまま行ってもよいのですが、FDMiでは大量のFDMiDataを配線が必要になる関係上、無秩序にFDMiFloatを増やすと大変なことになります。(なりました。)

そこで、FDMiDataの配置を自動化する、FDMiDataBusFDMiDataBusTerminalを使用します。

さて、2.3.3ではVechicle/Model/Input/GearLever/GearLever(FDMiLeverInputの親)にFDMiDataBusTerminalを配置したかと思います。FDMiDataBusTerminal「+」ボタンを押して、以下を追加します。 FDMiDataBusTerminal

  • チェックボックス:☑(有効)
    • ☑(有効):この機体全体に設定を波及させます。
    • ☐(無効):このFDMiDataBusTerminalの子のみで使用する変数として扱います。
  • global Name: "GearLever"
    • 機体全体で、この変数を指す名前として使用します。FDMiDataBusTerminalは、ここで設定した名前をもとに、"GearLever"を探し(無ければ自動生成し)ます。
  • local Name: "LeverOutput"
    • FDMiDataBusTerminalの子にあるComponentの、FDMiDataを代入する項目の変数名がlocal Nameと一致した際、Global Nameで紐づいたFDMiDataを自動で代入します。
  • 変数型: FDMiFloat
    • 変数型を指定します。local Nameの示す代入先に応じたFDMiDataの型を選択してください。 今回、LeverOutputFDMiFloatを代入すべき項目ですので、FDMiFloatを選択します。

2.3.5 自動設定

ここまで設定したら、Unity上部のメニューからFDMi/Setup All FDMi Componentsを選択してください。 自動設定すべき場所に、変数が自動配置されます。

注記

自動配置される場所は、以下の通りです。

  • FDMiData型(FDMiBool,FDMiFloat, FDMiVector3, FDMiSyncedFloat等)が代入される箇所
  • 変数の横に"Find"のボタンがある箇所

2.4 出力:ギアレバーの動作(FDMiTransformRotationDriver)

入力の結果を、出力に適用してみましょう。 まず、ギアレバーを動作させてみます。Vechicle/Model/Input/GearLeverの子に、FDMiTransformRotationDriverを含むGameObjectを作成します。 FDMiTransformRotationDriver

FDMiTransformRotationDriverは、FDMiDataに応じ、Transformを回転させます。

  • Value: のちほどFDMiDataBusTerminalで設定されます。
  • RotateTransform: 回転させたいTransformを選択します。今回はギアレバーに紐づいたボーンを選択しています。
  • RotateAxis: 回転させたい軸を選択します。軸はRotateTransformの、ローカルの軸です。
  • Multiplier: ValueFDMiFloatが持つ値に対し、RotateTransformを何°回転させたいかを設定します。
  • repeatValue: Valueの値に対し、繰り返しを設定します。計器の針など、一定の値(100ftとか)で0に戻したいときに使用します。

また、以下を設定します。以下は、負荷などを考えて使用してください。

  • moveOnValueChange: ☑(有効)
    • FDMiDataが「値の変更に伴うイベント」を受け取るたびに、Transformを回転させます
    • 毎フレーム動作するとmoveOnUpdateより重いですが、数分に一回呼ばれる程度であればこちらの方が軽量です。
  • moveOnUpdate: ☐(無効)
    • Update毎にTransformを回転させます。
    • 毎フレーム動作するもの(計器など)では、moveOnValueChangeより軽くなります。

次に、FDMiDataBusTerminalに、以下を追加します。

  • チェックボックス:☑(有効)
  • global Name: "GearLever"
  • local Name: "Value"
  • 変数型: FDMiFloat

ここまで設定されていれば、以下の状態になるはずです。 ここでUnity上部メニューからFDMi/Setup All FDMi Componentsを選択し、自動設定を実行してください。

Terminal_LeverAnim

ここまでできたら、VRChatでワールドに入り、椅子に座り、レバーを握ってみてください。 正常に設定できていれば、手の動きに応じてレバーが動作するはずです。 上手くいかないときは,FDMiLeverInputMuiltiplier、およびFDMiTransformRotationDriverMuiltiplierを確認してください。

2.5 出力:ギア格納・展開(FDMiAnimatorDriver)

警告

ここでは、「見た目」の変化のみを設定します。WheelColliderの設定は別で行います。

次に、ギアの格納アニメーションを作成してみます。
まず、ギアの格納をAnimatorに設定します。Animatorの設定については、モデル差がありますので詳細は割愛します。 今回は、以下の様なAnimatorを作成しました。

  • パラメータgearの値に応じて、ギアが展開する  - 0: 展開状態
    • 1: 格納状態

ここで、FDMiDataの値を用いてAnimatorのパラメータを変化させていきます。 ただし、GearLeverの値そのままだと、脚の格納が一瞬で終わってしまうため、「GearLeverを1にしたら、ゆっくり格納される」挙動を作成していきます。

完成形は以下の図に示す通りです。 GearLeverの値にディレイ(遅れ)をかけたFDMiFloat、GearRetractを用意し、その値をAnimatorに書き込みます。 AnimatorDriver_Overview

2.5.1 ディレイ(FDMiFloatMixer)

まず、GearLeverの値にディレイをかけます。これにはFDMiFloatMixerを使用します。 今回はVehicle/Control/Gearの子にFDMiFloatMixerを作成します。

FDMiFloatMixer

各項目は以下の通り設定します。

  • output: 出力先のFDMiFloatを設定します。
    • 今回はVehicle/Control/GearFDMiDataBusTermianlを置き、自動設定します。
  • data: 入力のFDMiFloatを設定します。
    • Outputは、各data総和に対しディレイやOutput Curveをかけた結果が代入されます。
    • 今回はVehicle/Control/GearFDMiDataBusTermianlを置き、自動設定します。
  • T: 0.2 = 1/5(s)
    • 入力に対する出力の遅れを定義します。
    • 今回は、5秒かけて脚を展開してほしいため、1/5=0.2を設定します
  • outputCurve: 入力の総和に対し、出力のマッピングを行います。横軸がdataの総和・縦軸がOutputになります
    • 今回はdataの総和とOutputが1:1対応になるような設定にします
  • useUpdate: ☐(無効)
    • Update()毎にOutputを変更します
  • useOnChange: ☑(有効)
    • dataが変更される毎にOutputを変更します

次に、Vehicle/Control/GearFDMiDataBusTermianlを配置します。

gear_mixer_terminal

  • GearRetract:出力です。です。FDMiFloatMixeroutputに代入されるよう設定します。
  • GearLever: 入力です。FDMiFloatMixerdataに代入されるよう設定します。
注記

FDMiData(FDMiFloat等)の配列に、FDMiDataBusTermianlから代入したいときは、配列の順に、配列名を書いてください。 (複数個のFDMiDataを、FDMiDataBusTerminalから代入することができます。)

ヒント

local Nameに入れる名称の正しい綴り(大文字/小文字)などがわからないときは、代入したい項目を**右クリックし、Copy Property Path**を行えば、正式名称をクリップボードにコピーできます。

copy_property_path

2.5.2 ギア格納・展開(FDMiAnimatorDriver)

次に、Animatorを動かしていきます。
まず、Animatorを設定します。今回はVehicle/ModelAnimatorコンポーネントを配置しました。 今回は、"gear"パラメータに応じて、脚の位置を稼働させるAnimationが配置されています。

Animator_Settings

それでは、Vechicleと同じ階層にあるAnimationDriver以下に、"gear"パラメータを変化させるFDMiAnimatorDriverを設定します。

AnimatorDriver_Settigns

  • AnimatorDriver/GearFDMiDataBusTerminalを配置します。
    • GearRetractを、配下のInputに自動設定されるよう設定します。
  • AnimatorDriver/Gearの子にFDMiAnimatorDriverを配置します。
    • Input: 入力です。FDMiDataBusTerminalから設定されます。
    • Animator: パラメータを変更させたい対象のAnimatorを設定します。今回はVehicle/Modelを選択しています。
    • Paramator: Animator内の、値を変化させたいパラメータに対応する文字列を記入します。今回は"gear"です。
    • outputValue: 横軸Input対し、縦軸Paramatorの値をどのように変化させるかを設定します

ここまでできたら、Unity上部メニューからFDMi/Setup All FDMi Componentsを選択し、自動設定を実行してください。 VRChat上で、ギアレバーを動かすと、脚が格納するようになります。

3. 同期の設定

このままでは、脚の格納・展開状態を、自分以外の人に伝えられないので、同期を設定します。 同期の設定方法は2通りあります。

  • FDMiFloatFDMiSyncedFloatに置き換える
  • FDMiSynedFloatArrayを使用する

今回は後者を使用します。
前者に対する後者のメリットは、同期したい/したくないを後から変更・管理しやすい点です。
(FDMiSyncedFloatを使うと、何が同期対象なのか分かりづらくなってしまう、それだけです。好みで使ってください。)

今回は、GearLeverを同期対象とします。直接的な展開・格納状態(GearRetract)は同期せず各個で計算する形にします。

syncedFloatArray

  • Vehicle/Sync/InputPeripheralFDMiDatabusTerminalを配置します。
    • GearLeverFDMiDatabusTerminal配下のdataに自動設定されるよう設定します。
  • Vehicle/Sync/InputPeripheralの子にFDMiSyncedFloatArrayを配置します。

ここまでできたら、Unity上部メニューからFDMi/Setup All FDMi Componentsを選択し、自動設定を実行してください。 これで、脚の格納状態が同期されるようになります。

4.アニメーション デバッグ

ここまでで、アニメーションが設定されたかどうかのテストを簡潔に行う方法を解説します。 FDMi/Setup All FDMi Componentsを押した後、Unity上でPlayモードにします。

Playmode

  1. Vehicle/Data(自動生成されたFDMiData)からGearLeverを探します。
  2. FDMiFloatDataの数字を"0"⇒"1"にしてみます。
  3. ClientSimUdonHelperRun Custom Eventから"trigger"を押します
  4. ギアレバーの動作と、ギアの格納をチェックします。

ここで、ギアレバーの位置・回転量がずれていたり、ギア格納アニメーションの速度見てみます。
おかしい場合は、各項目にもどって、パラメータを確認します。