2016年11月12日土曜日

Unityで今見てる物体を探す(あと終末のイゼッタ妄想)

このページを参考にした。
【Unity】視界の中央に入ったら光るCube - ちょっと未来


float minAngle = float.MaxValue;
GameObject selectedItem = null;

foreach (GameObject item in GameObject.FindGameObjectsWithTag("Selectable Items")) {
    float rad = Mathf.Acos(Vector3.Dot((
            item.transform.position -
            camera_.transform.position).normalized,
        camera_.transform.forward));

    if (minAngle <= rad) {
        continue;
    }

    minAngle = rad;
    selectedItem = item;
}

if (selectedItem != null) {
    // ほにゃらら 
}

Tagに"Selectable Items"が設定されてるゲームオブジェクトをすべてスキャンして視線と物体までの角度を計算する。現在のオブジェクトの角度が過去の角度の最小値よりも小さいならそのオブジェクトを変数に突っ込む。変数はnullクリアしてあるので、nullでないなら有効なオブジェクトが存在している。

このコードでは物体までの角度が一番少ないモノを得られるので、視界内に複数のオブジェクトが有るとき、視界の(というか画面の)一番真ん中に近い物体を得ることができる。ただし視界内にオブジェクトがない場合でも、FindGameObjectsWithTagに引っかかるオブジェクトが1個でもあればそれを検出してしまう。
それが嫌な場合、例えば「視線から20度以内に有る物体だけを検出したい」という場合なら、selectedItem != null && minAngle <= 0.35という風にする(minAngleはラジアンなことに注意)。foreachの中で角度の範囲を分岐する必用はない。


Unityはいままでほとんど触ったことが無かったけど、スクリプトをC#で書けるので楽。ドキュメントも結構しっかりしてるし(ウチは回線が細いのでオンラインドキュメントはつらいけど)。

以下終末のイゼッタネタバレ含むかも




ということでエスコンで敵機をロックオンするみたいな機能はできた。Yボタン長押しで注視、短押しで視線上の物体を選択、という感じ。
次は選択した物体に近づいたらその物体を配下に置ける、みたいな機能になるのかな。いきなりワープしてくるのは不自然だろうし、ミサイルの誘導プログラムみたいなの作らないと駄目なんだろうなぁ。
「選択可能な物体をひとまとめにした物体」みたいな機能も必要かも。例えば樽に10本くらい突っ込まれた剣をまとめて取り出すとか、一山20個くらいのランスをぜんぶ捕まえるとか、戦闘機の腹の下に付いた大量の剣もひとまとめで取り出したいし。
他にも複数の剣を複数の物体に追尾したりとかも必用なので、攻撃対象をまとめて選択するようなものも必用だし。

自分で動かす物体も剣やランスやライフルみたいな細長い物体だけじゃなく、敵の戦車を投げたりとかもするから、このあたりの処理の違いも考えなきゃ。


最初はゲーム化したとしてどういう操作になるのかを妄想してただけなのに、どうしてこうなった。

0 件のコメント:

コメントを投稿