Unity入門 : UnityでGenerative Artっぽい表現をしてみる。

 

開発用ノートPCがVAIO Zなので、3D作品制作と表現力向上のためにUnityを導入してみました。
とりあえず今週末は、Unityに慣れるために球体が徐々に崩壊するSketchを作るところまでやってみました。

作った作品はこちら。

 



三角関数で算出したPositionにSphereを配置していき、その軌跡で球体を作り、それが徐々に崩壊していくスケッチです。
崩壊していったときに、球の輪郭が認識され、崩壊した球の感じが強調されるようにラインで結んでみました。
(崩壊の数式が適当なので、崩壊がきれいじゃないですが、、、)

UnityはIDEがあるので、GameObjectの配置とかはGUIでできます。 まず空のGameObject(AbstractSphere)を用意して、そいつにSphereのプレハブをくっつけてScriptでインスタンス化していきます。 ここまでは割と簡単で、Processingコードもほぼそのまま移植できます。 GameObjectとAssetsはこんな感じになっています。

また、Sphereをインスタント化するときに空のGameObjectの子Objectとして作っておくと、 Sphereの集合体である球体をぐるぐるするのも、transform.Rotate()で簡単にできました。 で、次にLineを引くんですがLineRendererというものを利用しました。 LineRendererは1つのComponentだけで、複数の線描画を行えるらしく、Vertexの数とPositionの指定で指定した頂点を結ぶ線が描けるようです。 空のGameObject(AtstractSphere)のComponentとして利用していますが、Rotateなどに連動して描画された線は動いてくれないので、Positionを動かすたびに再指定する必要があります。 再指定するだけで、再描画されます。

LineRenderの使い方はこちらを参照しました。

AbstractSphereにくっつけたScriptコードはこちら。

#pragma strict

var radius : int = 10;
var sphere : Transform; //Sphere Assets
var line : LineRenderer; //LineRenderer Component

function Start () {
    var s : float = 0;
    var t : float = 0;

    line = GetComponent(LineRenderer);
    var index : int = 0;
    while (t < 180) {
        s += 32;
        t += 0.5;
        var radianS : float = s * Mathf.Deg2Rad;
        var radianT : float = t * Mathf.Deg2Rad;
 
        var thisx : float = 0 + (radius * Mathf.Cos(radianS) * Mathf.Sin(radianT));
        var thisy : float = 0 + (radius * Mathf.Sin(radianS) * Mathf.Sin(radianT));
        var thisz : float = 0 + (radius * Mathf.Cos(radianT));
        var newSphere = Instantiate(sphere, Vector3(thisx, thisy, thisz), Quaternion.identity);
        newSphere.transform.set_parent(gameObject.transform); //Set AbstractShpere as the parent of each sphere
 
       //draw line between shperes
        line.SetVertexCount(index+1);
        line.SetPosition(index, Vector3(thisx, thisy, thisz));
        index++; 
    }
}

function Update () {
    var index : int = 0;
    for(var child : Transform in transform){
        var x : float = child.position.x;
        var y : float = child.position.y;
        var z : float = child.position.z;
        child.position = Vector3(Mathf.Sin(Time.time)*Random.Range(-1.0,1.0) + x, y, z);
 
        //redraw lines
        line.SetPosition(index, Vector3(child.position.x,child.position.y,child.position.z));
        index++;
    }
    transform.Rotate(1.0,1.0,1.0);
}

Processingと違って、Unityは一度配置したGameObjectを操作して扱うことが前提になっているようです。(それ、普通かも) Processingでこのようなスケッチをする場合は、毎回位置計算をして全部描きなおすというコーディングをしていました。
そうすることで、数式の一部にノイズを載せたりすることでGenerativeな動きをコーディングしていたのですが、 Unityでは一度配置したGameObject群に対して計算式を当てることになるのかな?などと想像しています。(もっといい方法あるのかも。)

というかProcessingでやっていた方法だと、計算式上はとてもわかりやすいし数学的な実験はしやすいと思うんだけど、 実際にはわかりにくいけど、Processingの裏ではObjectが大量に生成されてすごく重くなるのかな…とか思いました。
Generatie Art本のサンプルコードなんだけど、効率はあまりよくないのかも?

とにかく、初心者なのでいろいろ弄りながら表現の幅を探索していきたいと思います。
目標はツイまんだらを、これを使ってより小宇宙的な表現に拡張すること!