Unityで移動や回転
観点毎における演算の機能
ベクトルを座標として使う時
足し算は移動になる。 移動地点 = 現在地 + 移動距離
引き算は距離になる。距離 = 目標 - 現在地
掛け算はあんま使わないような?
割り算は、座標のスナップ地点何かを作れる スナップ位置 = 距離 / スナップ数 * 値
2つのVector3が同じ向きかどうか調べる
Vector3.Dot(a, b) > 0 ? 同じ向き : 反対向き
Vector3.Dot(a, b) == 1 で完全一致。 -1で正反対
移動系
方向を決めて移動
code:cs
float speed = 12;
Vector2 moveDir = new Vector2(1,2).normalized;
transfomr.Translate(moveDir * speed * Time.deltaTime)
Transform.positionに毎フレーム加算 code:cs
float speed = 12;
Vector2 moveDir = new Vector2(1, 2).normalized;
transform.position += (moveDir * speed * Time.deltaTime);
どうもTranslateメソッドより性能が良いらしい +=じゃなく=で代入することで、ワープできる
code:cs
Rigidbody2D rig = gameobject.getComponent<Rigidbody2D>();
rig.velocity = new Vector2(x,y);
一度代入すると、物理演算ベースでその方向へ進み続けてくれる。
物理計算的な移動
code:cs
var acceleration = Vector3.zero;
var distance = target.position - my.position;
var period = Time.deltaTime; // FIXME 着弾時間を不定にするにはこれでええんか?
acceleration += 2*(distance - my.velocity * period) / (period * period);
if(acceleration.magnitude > 100f)
{
acceleration = acceleration.normalized * 100f; // 加速度の上限を設けて、誘導性能を下げる
}
velocity += acceleration * Time.deltaTime;
position += velocity * Time.deltaTime;
考え方的には「このフレームにおける」運動方程式の結果はなあに
回転系
色々難しいけど、要は軸を表す3次元ベクトルを決めて、ひねるように回転させる概念、だそうな。ねじねじ
デフォルトは右向きで、加算で反時計回り、減算で時計回りに回ると覚えておく。
code:cs
var diff = player.transform.position - this.transform.position;
float rad = Mathf.Atan2(diff.y, diff.x);
float deg = rad * Mathf.Rad2Deg;
ある種古典なんだと思う
Unityだともっと早い方法ありそう
EulerAnglesの謎挙動
計算の問題なのか、transform.eulerAngles.xの値が、ヨーの向きによって変わる(180だったり270だったりする)
code:cs
Vector3 rot = this.transform.rotation * Vector3.up;
掛け算の順序はQuaternionが左なので注意
向き先をベクトルで入力し、Quaternionに変換
code:cs
// プレーヤ座標 - 自分の座標でベクトルを算出。
var vect = (targetPos - myPos);
// 向きたい方向を作成
var toQuat = Quaternion.FromToRotation(Vector2.left, vect);
// 自分の向きを更新
this.transform.rotation = toQuat;
Quaternion同士の掛け算
Quaternion同士の掛け算は、角度の足し算になる
回転の順番が、掛け算の順番(掛ける数、掛けられる数)に従うので注意(掛け算の交換法則が成り立たない)
Vector2から角度を求める
Mathf.Atan2(distance.y, distance.x);
ラジアンが得られる
値域はPIから-PIまで
ラジアンを度に直すのはradian * Mathf.Rad2Deg
Vector2からQuaternionを求める
Quaternion.FromToRotation(Vector2.right, distance);
Vector2.rightは数学のグラフに合わせた場合。右向きのベクトルからdistance度回転させる(ためのQuaternionを求める)
角度からVector2を求める
new Vector2(Mathf.cos(radian), Mathf.sin(radian))
角度からQuaternionを求める
Quaternion.AngleAxis(digree, Vector3.forward)
Vector3.forwardは数学のグラフに合わせた場合。グラフの原点に鉛筆刺して回転させる感じ
Quaternionから角度を求める
code:cs
float degree;
rotation.ToAngleAxis(out degree, Vector3.forward);
QuaternionからVector2を求める
code:cs
Vector3 direction3 = rotation * Vector3.forward;
Vector2 direction = (Vector2)direction3;
Quaternionを使った自機狙い(回転速度上限付き)
code:cs
//
// Enemy
//
float enemy_speed = 11f;
foreach (Transform enemy in EnemyContainer)
{
var targetDirection = (player.position - enemy.position); // 目標の方向
var targetQuaternion = Quaternion.LookRotation(targetDirection); // 目標の姿勢
// LookAt
// enemy.rotation = targetQuaternion;
// RotateTowards 今の姿勢から目標の姿勢へ変換するが、変位に上限を設ける
enemy.rotation = Quaternion.RotateTowards(enemy.rotation, targetQuaternion, 100 * Time.deltaTime);
enemy.Translate(Vector3.forward * enemy_speed * Time.deltaTime); // 向いてる方向へ進む
}