読者です 読者をやめる 読者になる 読者になる

NinaLabo

個人ゲーム開発者の技術メモ

【C#】三角関数で2点間の線の長さと角度を計算する

下記のようなスキルツリーのミニマム版みたいなものを実装しているのですが、ボタンとボタンを繋ぐ線の長さと角度は計算して配置しています。

f:id:ninagreen:20161218030829p:plain

特定の2点間を線でつなぐのを Unity でどう書けばいいのか、いつもやりかたを忘れてしまうのでまとめておきます。

2点間の線の長さ

下記のような直角三角形があるとして、 

f:id:ninagreen:20161218035038p:plain

C^2 = A^2 + B^2 なので、

斜辺Cは、C = {\sqrt{A^2 + B^2}} で求められます。

 Unity で書くとこんな感じですかね。Powは累乗、Sqrtは平方根です。

float diffX = toX - fromX;
float diffY = toY - fromY;

float width = Mathf.Sqrt (Mathf.Pow (diffX, 2) + Mathf.Pow (diffY, 2));
lineTransform.sizeDelta = new Vector2 (width, lineTransform.sizeDelta.y);

lineTransform は、幅が1pxの画像のTransformです。

2点間の角度

同じく以下の直角三角形があるとして、

f:id:ninagreen:20161218035538p:plain

tanθ = B/A なので、

角度は、θ = tan^{-1}(B/A) = atan(B/A)

で求められます(あってるかな...)。atanはアークタンジェント(逆正接)です。高校ぐらいで習ったような気もしますが、使わないと忘れますね。

Unity だと atan を求める関数として、 Mathf.Atan と Mathf.Atan2 の2個用意されているのですが、そもそも atan は -π/2〜π/2 までの制限があり、xが正の値と負の値で区別がつかなくなってしまうので、360度で計算するときは Atan2 のほうが便利らしいです。

Unity のコードだとこんな感じ。Atan2関数は、第一引数がyで、第二引数がxです(これよく間違います...)。あと、yの値は上がプラスで下がマイナスなので別の座標系の場合は変換する必要があります(これもよく間違います...)。Atan2で求められる角度の単位はラジアン(Radian)なので Mathf.Rad2Deg で掛け算して、度(Degree)にしています。

float diffX = toX - fromX;
float diffY = toY - fromY; 

float radian = Mathf.Atan2(diffY, diffX);
float degree = radian * Mathf.Rad2Deg;
lineTransform.eulerAngles = new Vector3 (0, 0, degree);