Marauders日記_5 ZERO TO HERO [Behind Locked Doors] 攻略

ZERO TO HERO の 13個目のタスク
Iridium Asteroid Mine の溶鉱炉の左奥にある DEPOT の印のついてる扉を30秒間アクティベートする

溶鉱炉は上層部にあるので要注意、溶鉱炉周りにはそこそこAIがいるためある程度装備を整えてから行くと安定する
場所は↓の画像のところ

DEPOTの印がついている、この扉はトークンがないと開けられない( このタスクをクリアすると手に入る )

DEPOTの印がついた扉

Iridium Asteroid Mine の DEPOT を開くトーク

Marauders日記_4 ZERO TO HERO [Major Tom]、[Run Dry]攻略

ZERO TO HERO 11個目のタスク レーダータレットを5つ破壊するやつ
このタスク自体はかなり簡単、レイドの際にレイド拠点周辺にあるレーダータレットを破壊するだけ、いつものレイドのついでにタレットを壊すと思うので意識しなくてもすぐ終わる。

ただ紛らわしいのがこちらに攻撃してくる砲台はレーダータレットではないので注意が必要 ( カウントされない )

レーダータレット

ついでに12個目のタスク [Run Dry] も攻略
これはレーションクレートを3つ納品するもの、こればかりはレイドの場数を増やして Ration Creates を見つけて持って帰るほかない。

容量は正方形4マスなので Leather JekinとSack Bagを持っていけば十分拾える

Marauders日記_3 ZERO TO HERO [Merchant Inspector] 攻略

ZERO TO HERO の10個目のタスク
Merchant Inspector の目印のついたコンテナの場所は貨物区画の一番奥、エレベータのそばに白いコンテナがあるのでそれを3秒間アクティベートすると完了する

ここの一番奥

目印は若干わかりづらいが↓の画像の感じ

白いコンテナについている目印

エレベータから降りてくればすぐにアクセスできる

Marauders日記_2 自分の戦艦を建造

Zero to Hero の攻略しながらぼちぼち材料集めて自分の戦艦を建造。
デフォルトのおんぼろ戦艦から卒業できて良き。

My船

Zero to Hero の進捗は今のところこんな感じ、ただでさえエンカウント率の低い商船の中にある特定のコンテナを探すのはさすがに骨が折れそうな予感...

ちなみに建造した船は速攻でロストした

Marauders日記_1

10月から早期アクセスでリリースされた Marauders すごい僕好みだったんで即決で買って早10日くらい経過。 store.steampowered.com

右耳が聞こえないのもあってなかなかしんどいと思ってたけどコツをつかんでからは割と生き残れるようになった。
もし僕みたいに片耳が聞こえなくて難儀してる人は以下のポイントを抑えると生存率上がるかもしれないです。

できるだけ射線が通らないところを歩く

開けた場所だと射撃された時の方向を推定するのに時間がかかり、その間にキルされてしまう。 できるだけ通路など相手がいる方向を限定できる場所を選んで移動する。
通路であれば前にいなければ後ろにいる可能性が高い、等。
マップによっては広いところを通らなければならないケースもあるのでその時は足音は聞かれてでも狭い通路に入り込む。

部屋に入るとき or 出るときはフェイントを入れる

部屋に入るとき or 出るときは待ち構えてる側が圧倒的に有利なので一瞬顔を出してすぐひっこめる、これで慌てて撃ってくればそこに敵がいるのでその後は状況を見て打って出るか引くかを選択する。
人によっては引っ込んだこちらを追いかけてキルしようと距離を詰める人もいるので逆に待ち構えれば勝ち目が見えてくる。

中距離で撃ち合いをして相手に逃げられたら追いかけない

一つ上のポイントと被るけど待ち受ける側が圧倒的優位なので勝てそうかな?と思っても追いかけずにこちらも引っ込むほうが生存率が高い。
逆に向こうが追いかけてきたらめっけもん。

上の三点だけでもだいぶ生存率が上がる。

あとはたまに息抜きで装備はすべて現地調達縛りとか ( 意外と生き残れたりする )などもおすすめ。
宇宙海賊をエンジョイしましょう。

あと今やってる任務でOUTLAWの衣装がそろった、鉱山の炉の確保ってのがいまいちわからなくて最深部まで速攻で移動してうろちょろしてたけど残り時間4分あたりであきらめて帰ろうとしたら上層部に炉を見つけてその周りにいるレイダー ( 4, 5 人くらいいる )をキルして炉の周りにいるだけで時間が加算される。

炉は上層部にあるぞ!

OUTLAW衣装

MagicLeap2 コントローラ入力の情報まとめ

MagicLeap2 コントローラ入力サンプル - TechnicalProtein

↑の記事で触ったController Input Event についての追加情報、ここで紹介されている以外のボタン入力とかはこちらの記事に書いてます

SDK 0.53.3 現在の情報

UnityのInputSystemを利用してMagicLeap2のコントローラの入力をトリガーする方法のおさらい

using UnityEngine;
using UnityEngine.InputSystem;


namespace Sandbox.Controller
{
    /// <summary>
    /// コントローラ入力サンプル.
    /// </summary>
    public class ControllerInputSample : MonoBehaviour
    {

        private MagicLeapInputs _mlInputs;
        private MagicLeapInputs.ControllerActions _controllerActions;
        
        
        private void Start()
        {
            // 新しいインスタンスを作成し、起動.
            _mlInputs = new MagicLeapInputs();
            _mlInputs.Enable();

            // 各入力のイベントハンドラを登録.
            _controllerActions = new MagicLeapInputs.ControllerActions(_mlInputs);
            _controllerActions.Bumper.started += HandleOnBumperStarted;
            _controllerActions.Bumper.performed += HandleOnBumperPerformed;
            _controllerActions.Bumper.canceled += HandleOnBumperCanceled;
        }
    

        private void OnDestroy()
        {
            // 登録していたハンドラを削除.
            _controllerActions.Bumper.started -= HandleOnBumperStarted;
            _controllerActions.Bumper.performed -= HandleOnBumperPerformed;
            _controllerActions.Bumper.canceled -= HandleOnBumperCanceled;

            // 入力の購読を終了.
            _mlInputs.Dispose();
        }

       
        private void HandleOnBumperStarted(InputAction.CallbackContext obj)
        {
            Debug.Log("The Bumper is started.");
        }
        

        private void HandleOnBumperPerformed(InputAction.CallbackContext obj)
        {
            Debug.Log($"The Bumper is performed.");
        }


        private void HandleOnBumperCanceled(InputAction.CallbackContext obj)
        {
            Debug.Log($"The Bumper is canceled.");
        }
        
    }
}

手順としては

  1. MagicLeapInputs 、フィールド名 _mlInputs

  2. _mlInputs.Enable() で起動

  3. MagicLeapInputs.ControllerActions、フィールド名 controllerActions のインスタンスを作成時に mlInputs を渡し、関連付けを行う

  4. InputAction.CallbackContext を引数にとるイベントハンドラを作成

  5. 取得したい入力のイベントに登録 ( 今回は Bumper ボタン )

  6. 購読の用がなくなったら 登録したイベントを削除し、_mlInputs.Dispose() で入力の購読を終了する

購読するイベントタイプ

イベントタイプ 解説
InputAction.started 入力の開始時に呼び出される
InputAction.performed 入力されている間呼び出される
InputAction.canceled 入力が終了時に呼び出される

まとめ

簡単にだが MagicLeap SDKAPI を利用したコントローラ入力をまとめた
一応公式APIの入力をそのまま使う以外にMRTKを利用した入力も今度書こうと思う

MagicLeap2 コントローラ入力サンプル

やること

MagicLeap2 のコントローラの入力サンプルコードの紹介 動作確認は実機がないためMagicLeap HubのApplicationSimulatorにて確認しています

前提条件

↓の手順でMagicLeap2の開発環境を整えている必要があります

developer-docs.magicleap.cloud

サンプルスクリプト

マニフェストの設定

まずは Eidt > ProjectSettings > MagicLeap > ManifestSettings から CONTROLLER_POSE のチェックを入れる 執筆時点( 2022/9/19 SDK ver 0.53.3 )ではその項目はなかったが取れた

マニフェスト設定

スクリプト

UnityEngine.InputSystemを利用しているため、AssemblyDefinitionでアセンブリ空間を切ってる人は以下の参照の紐づけを忘れずに

  • MagicLeap.SDK
  • Unity.InputSystem

流れとしては MagicLeapInputs と MagicLeapInputs.ControllerActions のインスタンスを作成し、MagicLeapInputs.ControllerActions のインスタンスに MagicLeapInputs を紐づけ。 その後 MagicLeapInputs を起動し、購読したい入力のイベントを登録する。

namespace Sandbox.Controller
{
    /// <summary>
    /// コントローラ入力サンプル.
    /// </summary>
    public class ControllerInputSample : MonoBehaviour
    {

        private MagicLeapInputs _mlInputs;
        private MagicLeapInputs.ControllerActions _controllerActions;
        
        
        private void Start()
        {
            // 新しいインスタンスを作成し、起動.
            _mlInputs = new MagicLeapInputs();
            _mlInputs.Enable();

            _controllerActions = new MagicLeapInputs.ControllerActions(_mlInputs);
            _controllerActions.Bumper.performed += HandleOnBumper;

        }
    

        private void OnDestroy()
        {
            // 入力の購読を終了.
            _mlInputs.Dispose();
            _controllerActions.Bumper.performed -= HandleOnBumper;            
        }


        private void Update()
        {
            // Update で直接確認することも可能( Bumperボタン以外は省略 ).
            if (_controllerActions.Bumper.IsPressed())
            {
                Debug.Log("Update : IsBumperPressed");
            }

            // コントローラの座標と回転はワールド座標で取得される.
            //Debug.Log($"Controller Position {_controllerActions.Position.ReadValue<Vector3>()}");
            //Debug.Log($"Controller Rotation {_controllerActions.Rotation.ReadValue<Quaternion>().eulerAngles}");
        }


        private void HandleOnBumper(InputAction.CallbackContext obj)
        {
            bool bumperDown = obj.ReadValueAsButton();
            Debug.Log($"The Bumper is pressed down {bumperDown}");
        }

    }

}

サンプルコードのフル版

using UnityEngine;
using UnityEngine.InputSystem;


namespace Sandbox.Controller
{
    /// <summary>
    /// コントローラ入力サンプル.
    /// </summary>
    public class ControllerInputSample : MonoBehaviour
    {

        private MagicLeapInputs _mlInputs;
        private MagicLeapInputs.ControllerActions _controllerActions;
        
        
        private void Start()
        {
            // 新しいインスタンスを作成し、起動.
            _mlInputs = new MagicLeapInputs();
            _mlInputs.Enable();

            // 各入力のイベントハンドラを登録.
            _controllerActions = new MagicLeapInputs.ControllerActions(_mlInputs);
            _controllerActions.Bumper.started += HandleOnBumperStarted;
            _controllerActions.Bumper.performed += HandleOnBumperPerformed;
            _controllerActions.Bumper.canceled += HandleOnBumperCanceled;

            _controllerActions.Menu.started += HandleOnMenuStarted;
            _controllerActions.Menu.performed += HandleOnMenuPerformed;
            _controllerActions.Menu.canceled += HandleOnMenuCanceled;

            _controllerActions.Trigger.started += HandleOnTriggerStarted;
            _controllerActions.Trigger.performed += HandleOnTriggerPerformed;
            _controllerActions.Trigger.canceled += HandleOnTriggerCanceled;

            _controllerActions.TouchpadClick.started += HandleOnTouchpadClickStarted;
            _controllerActions.TouchpadClick.performed += HandleOnTouchpadClickPerformed;
            _controllerActions.TouchpadClick.canceled += HandleOnTouchpadClickCanceled;

            _controllerActions.TouchpadTouch.started += HandleOnTouchpadTouchStarted;
            _controllerActions.TouchpadTouch.performed += HandleOnTouchpadTouchPerformed;
            _controllerActions.TouchpadTouch.canceled += HandleOnTouchpadTouchCanceled;

            _controllerActions.TouchpadForce.started += HandleOnTouchpadForceStarted;
            _controllerActions.TouchpadForce.performed += HandleOnTouchpadForcePerformed;
            _controllerActions.TouchpadForce.canceled += HandleOnTouchpadForceCanceled;

            _controllerActions.TouchpadPosition.started += HandleOnTouchpadPositionStarted;
            _controllerActions.TouchpadPosition.performed += HandleOnTouchpadPositionPerformed;
            _controllerActions.TouchpadPosition.canceled += HandleOnTouchpadPositionCanceled;

            _controllerActions.IsTracked.started += HandleOnIsTrackedStarted;
            _controllerActions.IsTracked.performed += HandleOnIsTrackedPerformed;
            _controllerActions.IsTracked.canceled += HandleOnIsTrackedCanceled;
        }
    

        private void OnDestroy()
        {
            // 登録していたハンドラを削除.
            _controllerActions.Bumper.started -= HandleOnBumperStarted;
            _controllerActions.Bumper.performed -= HandleOnBumperPerformed;
            _controllerActions.Bumper.canceled -= HandleOnBumperCanceled;

            _controllerActions.Menu.started -= HandleOnMenuStarted;
            _controllerActions.Menu.performed -= HandleOnMenuPerformed;
            _controllerActions.Menu.canceled -= HandleOnMenuCanceled;

            _controllerActions.Trigger.started -= HandleOnTriggerStarted;
            _controllerActions.Trigger.performed -= HandleOnTriggerPerformed;
            _controllerActions.Trigger.canceled -= HandleOnTriggerCanceled;

            _controllerActions.TouchpadClick.started -= HandleOnTouchpadClickStarted;
            _controllerActions.TouchpadClick.performed -= HandleOnTouchpadClickPerformed;
            _controllerActions.TouchpadClick.canceled -= HandleOnTouchpadClickCanceled;

            _controllerActions.TouchpadTouch.started -= HandleOnTouchpadTouchStarted;
            _controllerActions.TouchpadTouch.performed -= HandleOnTouchpadTouchPerformed;
            _controllerActions.TouchpadTouch.canceled -= HandleOnTouchpadTouchCanceled;
            
            _controllerActions.TouchpadForce.started -= HandleOnTouchpadForceStarted;
            _controllerActions.TouchpadForce.performed -= HandleOnTouchpadForcePerformed;
            _controllerActions.TouchpadForce.canceled -= HandleOnTouchpadForceCanceled;
            
            _controllerActions.TouchpadPosition.started -= HandleOnTouchpadPositionStarted;
            _controllerActions.TouchpadPosition.performed -= HandleOnTouchpadPositionPerformed;
            _controllerActions.TouchpadPosition.canceled -= HandleOnTouchpadPositionCanceled;
            
            _controllerActions.IsTracked.started -= HandleOnIsTrackedStarted;
            _controllerActions.IsTracked.performed -= HandleOnIsTrackedPerformed;
            _controllerActions.IsTracked.canceled -= HandleOnIsTrackedCanceled;

            // 入力の購読を終了.
            _mlInputs.Dispose();
        }


        private void Update()
        {
            // Update で直接確認することも可能( Bumperボタン以外は省略 ).
            if (_controllerActions.Bumper.IsPressed())
            {
                Debug.Log("Update : IsBumperPressed");
            }

            // コントローラの座標と回転はワールド座標で取得される.
            //Debug.Log($"Controller Position {_controllerActions.Position.ReadValue<Vector3>()}");
            //Debug.Log($"Controller Rotation {_controllerActions.Rotation.ReadValue<Quaternion>().eulerAngles}");
        }


        #region --- Menu Button ---
        
        private void HandleOnMenuStarted(InputAction.CallbackContext obj)
        {
            Debug.Log("The Menu is started");
        }


        private void HandleOnMenuPerformed(InputAction.CallbackContext obj)
        {
            Debug.Log("The Menu is performed");
        }


        private void HandleOnMenuCanceled(InputAction.CallbackContext obj)
        {
            Debug.Log("The Menu is canceled");
        }
        
        #endregion --- Menu Button ---


        #region --- Bumper Button ---
        
        private void HandleOnBumperStarted(InputAction.CallbackContext obj)
        {
            Debug.Log("The Bumper is started.");
        }
        

        private void HandleOnBumperPerformed(InputAction.CallbackContext obj)
        {
            Debug.Log($"The Bumper is performed.");
        }


        private void HandleOnBumperCanceled(InputAction.CallbackContext obj)
        {
            Debug.Log($"The Bumper is canceled.");
        }
        
        #endregion --- Bumper Button ---

        
        #region --- Trigger ---

        private void HandleOnTriggerStarted(InputAction.CallbackContext obj)
        {
            Debug.Log($"The Trigger started value : {obj.ReadValue<float>()}");
        }


        private void HandleOnTriggerPerformed(InputAction.CallbackContext obj)
        {
            Debug.Log($"The Trigger performed value : {obj.ReadValue<float>()}");
        }


        private void HandleOnTriggerCanceled(InputAction.CallbackContext obj)
        {
            Debug.Log($"The Trigger canceled value : {obj.ReadValue<float>()}");
        }
        
        #endregion --- Trigger ---
        
        
        #region --- Touchpad Click ---

        private void HandleOnTouchpadClickStarted(InputAction.CallbackContext obj)
        {
            Debug.Log($"The Touchpad Click started {obj.ReadValueAsButton()}");
        }


        private void HandleOnTouchpadClickPerformed(InputAction.CallbackContext obj)
        {
            Debug.Log($"The Touchpad Click performed {obj.ReadValueAsButton()}");
        }


        private void HandleOnTouchpadClickCanceled(InputAction.CallbackContext obj)
        {
            Debug.Log($"The Touchpad Click canceled {obj.ReadValueAsButton()}");
        }

        #endregion --- Touchpad Click ---

        
        #region --- Touchpad Touch ---

        private void HandleOnTouchpadTouchStarted(InputAction.CallbackContext obj)
        {
            Debug.Log("The TouchPad Touch started.");
        }


        private void HandleOnTouchpadTouchPerformed(InputAction.CallbackContext obj)
        {
            Debug.Log("The TouchPad Touch performed.");
        }

        
        private void HandleOnTouchpadTouchCanceled(InputAction.CallbackContext obj)
        {
            Debug.Log("The TouchPad Touch canceled.");
        }

        #endregion --- Touchpad Touch ---
        
        
        #region --- Touchpad Force ---

        private void HandleOnTouchpadForceStarted(InputAction.CallbackContext obj)
        {
            Debug.Log("The Touchpad Force started.");
        }

        
        private void HandleOnTouchpadForcePerformed(InputAction.CallbackContext obj)
        {
            Debug.Log("The Touchpad Force performed.");
        }

        
        private void HandleOnTouchpadForceCanceled(InputAction.CallbackContext obj)
        {
            Debug.Log("The Touchpad Force canceled.");
        }
        
        #endregion --- Touchpad Force ---
        
        
        #region --- Touchpad Position ---
        
        /// <summary>
        /// 中心座標が0のタッチパッド上の XY 座標値.
        /// </summary>
        private void HandleOnTouchpadPositionStarted(InputAction.CallbackContext obj)
        {
            Debug.Log($"The Touchpad Position started value {obj.ReadValue<Vector2>()}");
        }

        
        private void HandleOnTouchpadPositionPerformed(InputAction.CallbackContext obj)
        {
            Debug.Log($"The Touchpad Position performed value {obj.ReadValue<Vector2>()}");
        }

        
        private void HandleOnTouchpadPositionCanceled(InputAction.CallbackContext obj)
        {
            Debug.Log($"The Touchpad Position canceled value {obj.ReadValue<Vector2>()}");
        }

        #endregion --- Touchpad Position ---
        
        
        #region --- IsTracked ---

        /// <summary>
        /// コントローラが接続しているか判定.
        /// なぜかはわからんが Started は呼ばれない.
        /// 接続したときに Performed が一度呼ばれる.
        /// 切断したときに Canceled が一度呼ばれる.
        /// 常に把握したい場合は Update() なりで常時監視したほうがいいかも?
        /// </summary>
        private void HandleOnIsTrackedStarted(InputAction.CallbackContext obj)
        {
            Debug.Log("The IsTracked started.");
        }
        

        private void HandleOnIsTrackedPerformed(InputAction.CallbackContext obj)
        {
            Debug.Log("The IsTracked performed.");
        }


        private void HandleOnIsTrackedCanceled(InputAction.CallbackContext obj)
        {
            Debug.Log("The IsTracked canceled.");
        }
        
        #endregion --- IsTracked ---
    }
}


触ってみた感想としてはボタン系の入力は基本イベント購読の形で行うのがよいかと思います、コントローラの座標や回転はイベント購読では取得できなかったのでUpdate()などで都度取得するのがよいかなと思います。

今後以下のリポジトリで触ってみたサンプルとかを増やしていく予定です github.com