ことばアルバム

にわかエンジニアのにわか備忘録

なぞった軌跡でオブジェクトを作る

Unityでなぞった軌跡をオブジェクトにして遊ぶようなゲームを作ろうとした時のメモ。

文字では伝わらないと思うのですが、こんな感じです。

f:id:is4cafe:20140303230722g:plain

サンプルはこちら(※PC限定)
https://dl.dropboxusercontent.com/u/73913606/nazoru/v1/nazoru.html


実装の話

処理の流れとしては以下の通りです。

 

  1. マウスのクリック(down)を検出する
    • クリックされた場所とScreenPointToRay()を使ってRayを作成
    • Physics.Raycastを使ってオブジェクトを生成できる場所か判定
    • RaycastHitのpointの座標に空のオブジェクトを生成
  2. マウスのクリック中を検出する
    • クリックされてる座標にオブジェクトを生成
    • 1で生成した空のオブジェクトの子要素にする
  3. マウスのクリック(up)を検出する
    • 1で生成した空オブジェクトにRigidBodyを付加する

 
 

下記は実際のコードです。

#pragma strict

var vertex : GameObject;
var parent : GameObject;
var nowParent : GameObject = null;
var lastPos;

function Start () {
    lastPos = transform.position;
}


function Update () {

    if (Input.GetMouseButtonDown(0)) {
        CreateEmpty();
    }

    if (Input.GetMouseButton(0)) {
        DrawLine();
    }

    if (Input.GetMouseButtonUp(0)) {
        nowParent.AddComponent(Rigidbody);
        nowParent = null;
    }

}

function CreateEmpty() {
    var pos = Input.mousePosition;
    var ray = Camera.main.ScreenPointToRay (pos);
    var hit : RaycastHit;
    if (Physics.Raycast (ray, hit, 100)) {
        var target = hit.point;
        target.z = 2;
        nowParent = Instantiate (parent, target, transform.rotation);
        nowParent.transform.parent = gameObject.transform;
    }    
}

function DrawLine() {
    var pos = Input.mousePosition;
    if (pos == lastPos) {
        return;
    }
    var ray = Camera.main.ScreenPointToRay (pos);
    var hit : RaycastHit;
    if (Physics.Raycast (ray, hit, 100)) {
        var target = hit.point;
        target.z = 2;
        var obj : GameObject = Instantiate (vertex, target, transform.rotation);
        obj.transform.parent = nowParent.transform;
        lastPos = pos;
    }
}

 

実際の軌跡(見えてるオブジェクト)ではなく、親となるオブジェクトを中心として操作していくために、全体として一塊のオブジェクトのように扱う事ができています。
スクリプト内で親子関係を作るときは

obj.transform.parent = nowParent.transform;

こんな感じでtransform.parentをいじってあれば大丈夫。
 
ポイントとなるのは、

var ray = Camera.main.ScreenPointToRay (pos);

の部分です。
ここではメインカメラから真正面に向かってのRayを取得しています。
カメラの設定にもよりけりなのですが、PerspectiveOrthographicのうち、Orthographicでないとうまく動作しません。
また、そのRayを使ったRaycastHitのpointを取得することで、画面上の座標からゲーム内の座標に変換しているのも大事なところです。
 

今回は分かりやすいように球を薄っぺらくしたものを軌跡としましたが、ここは応用次第で何にでも出来そうです。
現状の課題としてはマウスの移動が早すぎると何も無い箇所が出来てしまうのもなんとかしないといけないところですね。
あと、スマホの場合は、マウスクリックをタップに書き換えるだけで良いのかな?
ここら辺は今度試してみます。