デモ
早速ですが、デモです。
OculusQuestのプレイエリア設定画面などもゆっくりとUIがプレイヤーの視線に追従するようになってます。
コード
usingUnityEngine;/// <summary>/// 視線に追従させたいオブジェクトにアタッチ/// </summary>publicclassFollowEyeDirection:MonoBehaviour{[SerializeField,Range(0.1f,1.0f)]privatefloat_positionLerpSpeed=0.1f;[SerializeField,Range(0.1f,1.0f)]privatefloat_rotationLerpSpeed=0.1f;[SerializeField]privatefloat_distanceForwards=5f;[SerializeField]privatefloat_distanceUpwards=1f;privatevoidUpdate(){//正面に移動floatposSpeed=_positionLerpSpeed;Vector3posTo=Camera.main.transform.position+(Camera.main.transform.forward*_distanceForwards)+(Camera.main.transform.up*_distanceUpwards);transform.position=Vector3.Slerp(transform.position,posTo,posSpeed);//正面方向に回転floatrotSpeed=_rotationLerpSpeed;QuaternionrotTo=Quaternion.LookRotation(transform.position-Camera.main.transform.position);transform.rotation=Quaternion.Slerp(transform.rotation,rotTo,rotSpeed);}}
Lerp,Slerp
以前書いた記事でも取り上げたんですが、
Update内での挙動がいまいちよくわかってなかったのでもっかいまとめます。
【参考リンク】:Mathf.Lerp
まずはそれぞれの動き方について簡単に流して見ていきます。
Lerp
左右にカメラを振ると、直線的に追従してきます。
Slerp
左右にカメラを振ると、曲線を描きながら(分かりづらいですが)追従してきます。
Lerpの使い方
Slerp
も挙動が違うだけで使い方は一緒なのでLerp
についてのみ書きます。
Vector3.Lerp(a, b, t)
のように使い、t
でa
とb
の間を補間します。
それぞれの引数の説明は下記です。
a : 始点となるベクトル位置(型:Vector3)
b : 終点となるベクトル位置(型:Vector3)
t : 両端の距離を1とした時の割合(型:float, 0~1の範囲のみ)
【参考リンク】:[Unity] Vector3.Lerpの使い方
Update内で起きている処理のイメージ
privatevoidUpdate(){transform.position=Vector3.Lerp(transform.position,目的地点,移動の割合);}
今回の追従で利用した上記のコードを図解します。
※移動の割合は今回は0.2として話を進めます
結論を先に言うと、
第一引数である開始地点に移動させたいオブジェクトの座標を入れておくと
イイ感じにフワーって動いてくれるって感じです(語彙力)。
上記では説明としてザックリ過ぎるので、もう少し細かく考えていきます。
Lerp関数の第三引数で指定した割合を使って、
開始地点から見た、目的地点までの20%の位置を算出します。
つまり、1フレーム目で実際に20%分、目的地まで進みます。
2フレーム目も同様に進みますが、先ほどの開始地点とは異なり、
すでに20%移動した先が開始地点となります。
つまり、2フレーム目では、
その時点での開始地点から目的地点までの20%分またさらに進むということです。
この20%分の移動を目的地点に到達するまで繰り返す、、、
というイメージです。
ポイントとしては
1フレーム分の移動の変化量がだんだん小さくなり、緩やかな曲線を描く
ということです。
この変化量の減衰のおかげでイイ感じにフワーってなります。
図解では少しわかりづらいですが、
20%のまたさらに20%、そのまたさらに20%、、、
というのを繰り返すことで、変化量がだんだんと小さくなります。
参考リンク
下記プロジェクト内のコードを使用させていただいてます。
【GitHub】:MagicLeapHandTracking