今回はUnityのVector3.SmoothDamp、Mathf.SmoothDamp、Mathf.SmoothDampAngle、Mathf.SmoothStepを使用しゲームオブジェクトの移動や回転、色の変更等を滑らかにしてみようと思います。
わたくしの記事で滑らかな遷移をさせるにはVector3.LerpやVector3.Slerp等を使っていました。
↑の記事でどんな動きになるか実験しています。
今回は別のやり方で徐々に値を変化させていきます。
徐々に値を変化させる
今回使用するメソッドを一つ一つ見ていきましょう。
Vector3.SmoothDamp
Vector3.SmoothDampはVector3型の値を徐々に変化させていきます。
現在地から目的地に徐々に移動させたい場合に使います。
1 2 3 | Vector3.SmoothDamp (現在地, 目的地, ref 現在の速度, 遷移時間, 最高速度); |
第1引数がVector3の現在の位置、第2引数がVector3の目的の位置、第3引数がVector3の現在の速度、第4引数が目的地までの遷移時間、第5引数が移動の最高スピードになります。
第5引数は指定しなくても大丈夫です。
戻り値としてVector3の値が返ってくるのでこれを現在地に再度代入する事で少しづつ移動させる事が出来ます。
第3引数のrefは参照渡しで使用するもので、現在の速度は実行する度に変更されここで指定した変数に代入されます。
ここら辺はとりあえずrefというキーワードを書く必要があるという認識だけで詳しくはC#のリファレンスを確認してください。
Mathf.SmoothDamp
Mathf.SmoothDampはVector3.SmoothDampのfloat型の値を得られるバージョンです。
ある値を目的の値に徐々に変更していきます。
1 2 3 | Mathf.SmoothDamp (現在の値, 目的の値, ref 現在の速度, 遷移時間, 最高速度); |
第1引数はfloat型の現在の値、第2引数がfloat型の目的の値、第3引数はfloat型の現在の速度、第4引数が遷移時間、第5引数が移動の最高スピードになります。
Mathf.SmoothDampAngle
Mathf.SmoothDampAngleは1つの角度を徐々に変更させる為のメソッドです。
1 2 3 | Mathf.SmoothDampAngle (現在の角度, 目的の角度, ref 現在の速度, 遷移時間, 最高速度); |
引数はfloat型でこれまで紹介したメソッドと同じです。
Mathf.SmoothStep
Mathf.SmoothStepは補間をします。
Mathf.Lerpと機能は同じですね?
1 2 3 | Mathf.SmoothStep (現在の値, 目的の値, 割合) |
第1引数がfloat型の現在の値、第2引数がfloat型の目的の値、第3引数では割合を指定します。
割合が0なら現在の値、1以上なら目的の値を返し、0.5なら半分の値を返します。
徐々に値を変化させるサンプルの作成
スムーズに値を変化させるメソッドを見てきたので、それらを使ったサンプルを作成してみます。
今回作成するサンプルはカメラの移動と回転、カメラに映る背景色の変化をさせてみます。
ヒエラルキーで右クリック→3D GameObject→Cubeを選択し名前をTargetとし、このゲームオブジェクトの位置と角度にカメラを遷移させます。
その為、作成したTargetのTransformを変更してください。
Targetの位置や角度は↑のように設定しました。
↑がカメラとTargetの位置関係です。
カメラがTargetの位置と角度に遷移していくスクリプトを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | using UnityEngine; using System.Collections; public class SmoothMove : MonoBehaviour { [SerializeField] private Transform target; // カメラの到達点 [SerializeField] private float moveSpeed; // カメラの移動速度 [SerializeField] private float duration; // カメラの移動間隔 [SerializeField] private float rotateSpeed; // カメラの回転スピード [SerializeField] private float colorSpeed; // 色変化のスピード [SerializeField] private float maxSpeed; // 最高速度 [SerializeField] private Color backColor; // カメラの背景の色 private Vector3 moveVelocity; // 現在の移動の速度 private float xVelocity; // 現在の回転の速度 private float yVelocity; // 現在の回転の速度 private float zVelocity; // 現在の回転の速度 private Vector3 allRotateVelocity; // 全ての角度を変える場合に使用する速度 private float colorVelocity; // 色変化用の現在の速度 private float startTime; // 開始時間 void Start () { startTime = Time.time; } void Update () { // 位置をスムーズに動かす // transform.position = Vector3.SmoothDamp (transform.position, target.position, ref moveVelocity, moveSpeed * Time.deltaTime, maxSpeed); // 位置をスムーズに動かすSmoothStep版 var t = (Time.time - startTime) / duration; var xPos = Mathf.SmoothStep (transform.position.x, target.position.x, t); var yPos = Mathf.SmoothStep (transform.position.y, target.position.y, t); var zPos = Mathf.SmoothStep (transform.position.z, target.position.z, t); transform.position = new Vector3(xPos, yPos, zPos); // カメラの角度をスムーズに動かす var xRotate = Mathf.SmoothDampAngle (transform.eulerAngles.x, target.eulerAngles.x, ref xVelocity, rotateSpeed * Time.deltaTime, maxSpeed); var yRotate = Mathf.SmoothDampAngle (transform.eulerAngles.y, target.eulerAngles.y, ref yVelocity, rotateSpeed * Time.deltaTime, maxSpeed); var zRotate = Mathf.SmoothDampAngle (transform.eulerAngles.z, target.eulerAngles.z, ref zVelocity, rotateSpeed * Time.deltaTime, maxSpeed); transform.eulerAngles = new Vector3 (xRotate, yRotate, zRotate); // カメラの背景色を変更 var colorR = Mathf.SmoothDamp (Camera.main.backgroundColor.r, backColor.r, ref colorVelocity, colorSpeed * Time.deltaTime, maxSpeed); var colorG = Mathf.SmoothDamp (Camera.main.backgroundColor.g, backColor.g, ref colorVelocity, colorSpeed * Time.deltaTime, maxSpeed); var colorB = Mathf.SmoothDamp (Camera.main.backgroundColor.b, backColor.b, ref colorVelocity, colorSpeed * Time.deltaTime, maxSpeed); Camera.main.backgroundColor = new Color (colorR, colorG, colorB, 1f); } } |
カメラの位置の移動は2つのバージョンを作成しました。
一つ目はVector3.SmoothDampを使ってターゲットのゲームオブジェクトの位置に徐々に移動させています。
二つ目はMathf.SmoothStepを使ってX、Y、Zの値をそれぞれ計算し、カメラの位置を徐々に移動させています。
サンプルを実行する時はどちらかをコメント化して実行してください。
SmoothStepの第3引数には経過時間を間隔で割った値を指定します。
SmoothDampは徐々に値を変化させますが、SmoothStepは最初と最後がゆっくりになります。
Mathf.SmoothDampAngleを使ってカメラの角度をTargetの角度へと徐々に変化させています。
Mathf.SmoothDampを使ってカメラの背景色のR、G、Bの値を徐々に目的の値に変化させています。
スクリプトをMain Cameraに設定しパラメータを変更します。
Back Colorの色ではR、G、Bに255、Alphaに0を設定します。
またMain CameraのCameraのClear FlagsをSolid Colorに変更しカメラに映る背景を通常の色にします。
これで設定が出来たので実行してみましょう。
↑のようになりました。
今回は位置の移動でSmoothStepを使用しました。
JavaScriptで使用する場合
C#の場合はrefというキーワードが必要ですが、JavaScriptの場合は付けずに使用します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | #pragma strict @SerializeField private var target : Transform; // カメラの到達点 @SerializeField private var moveSpeed : float; // カメラの移動速度 @SerializeField private var duration : float; // カメラの移動間隔 @SerializeField private var rotateSpeed : float; // カメラの回転スピード @SerializeField private var colorSpeed : float; // 色変化のスピード @SerializeField private var maxSpeed : float; // 最高速度 @SerializeField private var backColor : Color; // カメラの背景の色 private var moveVelocity : Vector3; // 現在の移動の速度 private var xVelocity : float; // 現在の回転の速度 private var yVelocity : float; // 現在の回転の速度 private var zVelocity : float; // 現在の回転の速度 private var allRotateVelocity : Vector3; // 全ての角度を変える場合に使用する速度 private var colorVelocity : float; // 色変化用の現在の速度 private var startTime : float; // 開始時間 function Start () { startTime = Time.time; } function Update () { // 位置をスムーズに動かす // transform.position = Vector3.SmoothDamp (transform.position, target.position, ref moveVelocity, moveSpeed * Time.deltaTime, maxSpeed); // 位置をスムーズに動かすSmoothStep版 var t = (Time.time - startTime) / duration; var xPos = Mathf.SmoothStep (transform.position.x, target.position.x, t); var yPos = Mathf.SmoothStep (transform.position.y, target.position.y, t); var zPos = Mathf.SmoothStep (transform.position.z, target.position.z, t); transform.position = new Vector3(xPos, yPos, zPos); // カメラの角度をスムーズに動かす var xRotate = Mathf.SmoothDampAngle (transform.eulerAngles.x, target.eulerAngles.x, xVelocity, rotateSpeed * Time.deltaTime, maxSpeed); var yRotate = Mathf.SmoothDampAngle (transform.eulerAngles.y, target.eulerAngles.y, yVelocity, rotateSpeed * Time.deltaTime, maxSpeed); var zRotate = Mathf.SmoothDampAngle (transform.eulerAngles.z, target.eulerAngles.z, zVelocity, rotateSpeed * Time.deltaTime, maxSpeed); transform.eulerAngles = new Vector3 (xRotate, yRotate, zRotate); // カメラの背景色を変更 var colorR = Mathf.SmoothDamp (Camera.main.backgroundColor.r, backColor.r, colorVelocity, colorSpeed * Time.deltaTime, maxSpeed); var colorG = Mathf.SmoothDamp (Camera.main.backgroundColor.g, backColor.g, colorVelocity, colorSpeed * Time.deltaTime, maxSpeed); var colorB = Mathf.SmoothDamp (Camera.main.backgroundColor.b, backColor.b, colorVelocity, colorSpeed * Time.deltaTime, maxSpeed); Camera.main.backgroundColor = new Color (colorR, colorG, colorB, 1f); } |
SerializeFieldアトリビュートは[]ではなく最初に@を付け、refキーワードの部分を削除すればC#と同じように動作します。
終わりに
SmoothDamp等はrefキーワードを入れる必要があったので全然使っていなかったんですが、現在の速度も取得する事が出来るので用途によってはこちらの方が使い勝手がいいのかもしれません。
SmoothStepはMathf.Lerpと同じような感じですが、まったく同じかどうかはわかりませんでした・・・・(^_^;)