はじめに
タイトルの通り、ある水平軸に対して指定オブジェクト(今回はカメラ)が上側にあるか、下側にあるかを判定する方法についてまとめます。
Script及び注意点
まず、スクリプトから
public bool IsUp(Transform Target,Transform Cam)
{
var diff = Target.transform.position - Cam.transform.position;
var axis = Vector3.Cross(Target.transform.forward,diff);
return axis.x > 0;
}
判定自体はこの三行で行えます。
しかし、注意点として例えばTargetの原点が以下のように足元(0地点)にある場合、Target.transform.fowrd
で求まる水平軸は足元にくるため、カメラが真下に潜り込まない限り基本的には判定は常にTrue
が返ってきてしまいます。
よって、Targetの中央高さを基準水平軸としたい場合は、Targetの子として空のオブジェクトを配置し、そのオブジェクトをTargetにセットすることで解決します。
なぜ、この判定を行う必要があったのか
そもそもなぜこのような判定方法を取る必要があったかというと、Unityにおいて回転の値はEditor上で入力する「-50」と「310」は全く同じ角度となります。
しかしながら、この値をスクリプトから取得すると、返ってくるのはどちらの値でも「310」が返ってきます。
こうなると何が困るかというと、例えばCam01
からCam02
に回転値「-50」を引き継ぐ場合、以下のような事が起こりえます。
そのため、何らかの方法で回転値を判定し、正しい値を受け渡す処理が必要だったわけです。
今回はベクトルから上下を判定しましたが、調べた中でもう一つ簡単に判定する方法も見つけたので、併せて紹介しておきます。
おまけ(回転値を+180~-180に整える)
public float AdjustAngle180(float angle)
{
float subNormal = Mathf.Floor((angle + 180f) / 360f) * 360f;
return (angle > 0f) ? angle - subNormal : angle;
}
angle
に回転値を渡します、渡す際はtransform.rotation.eulerAngles
でQuaternion型からVecotr3型にキャストしてから渡しましょう。
subNormal
は「0」または「360」となります、水平軸より上側なら「0」、下側なら「360」です。
これを0以上かどうか判定し、0以上の場合は取得したangle
から-360してマイナスの値に、そうでなければそのままの値を返します。
結果としては先述したベクトルから求める方法と同じ結果となるため、どちらを使っても問題ないと思います。