回転は一見単純な操作だが、すぐ忘れるので備忘録代わりに書いておく。
プリミティブをの円柱(Cylinder)を新規作成した場合、
transform.right :グローバルX方向&ローカルX方向=半径方向1 transform.up :グローバルY方向&ローカルY方向=円柱の軸方向 transform.forwad: グローバルZ方向&ローカルZ方向=半径方向2
となる。
この円柱を
transform.Rotate(new Vector3(90.0f, 0.0f, 0.0f))
と、X軸周りに90度回転させる。(円柱の軸は水平方向に向く)
このとき、
transform.right :グローバルX方向&ローカル半径方向1 transform.up :グローバルZ方向&ローカル軸方向 transform.forwad: グローバル-Y方向&ローカル半径方向2
となる。
つまり、ある軸まわりの回転は、その軸を手前から向こうに向かう方向から見たとき、反時計回りの回転となる。ねじ回しでいうと、ねじを外す方向。
当然のことだが、ローカル座標は物体にくっついて方向を変える。円柱の場合、軸方向は常にローカルY軸となる。
この円柱を軸方向に動かしたい時、どうするか。
obj.transform.Translate(10*obj.transform.up);
と書いてしまいそうだが、これではだめ。Translate()はデフォルト(=Translateの第二引数が`Space.Self`の状態)ではグローバル座標で方向を指定するからだ。
下の画像は、青い球の中心に生成した円柱を、青い球の半径分、円柱の軸方向に動かそうとしたもの。しかし、軸方向ではなく円柱の半径方向に動いてしまっている。これは、グローバル座標で(0.0, 0.0, 1.0)であるtransform.upを、円柱のローカル座標で動かしているため、矛盾が生じてしまったのだ。つまり、円柱の軸は水平を向いているが、円柱ローカルのZは下を向いているので、下方に移動してしまう。
円柱の軸方向に動かすには、Translateの第二引数に'Space.World'を指定し、
obj.transform.Translate(10*obj.transform.up, Space.World);
とすればよい。これで、グローバルで見ているtransform.upを、正しくグローバル座標で移動できる。
ランダムに与えた緯度・経度の示す地球表面上の地点に、垂直に円柱を立てるには次のようにすればよい。
void Update () { if(count < 20) { cylinder = GameObject.CreatePrimitive(PrimitiveType.Cylinder); cylinder.transform.position = Vector3.zero; Debug.Log (cylinder.transform.up); //(0.0, 1.0, 0.0) cylinder.transform.localScale = new Vector3(cylinderRadius, cylinderHeight, cylinderRadius); lat = Random.Range(-80.0f,80.0f); //latitude lng = Random.Range(-180.0f,180.0f); //longitude cylinder.transform.Rotate(new Vector3(-90.0f, 0.0f, 0.0f), Space.Self); //rotate 90 around X to equator Debug.Log (cylinder.transform.up); //(0.0, 0.0, 1.0) cylinder.transform.Rotate(new Vector3(0.0f, 0.0f, -lng), Space.Self); //rotate in longitude direction cylinder.transform.Rotate(new Vector3(lat, 0.0f, 0.0f), Space.Self); cylinder.transform.Translate((sphereRadius+cylinderHeight)*cylinder.transform.up, Space.World); }; count++; }