藍と淡々

物作り冒険譚


【Unity】知って得するMathfクラス

こんにちは(ؓؒؒؑؑؖؔؓؒؐؐ⁼̴̀ωؘؙؖؕؔؓؒؑؐؕ⁼̴̀ )

今回はUnityのMathfクラスの紹介をしていきたいと思います。

といっても全部は大変なので、よく使うっぽいやつ&イメージしやすいやつだけ。(アバウト過ぎる…)

具体例はUnityのスクリプトリファレンスからパクってきました!イガ栗⊂( ・∀・) 彡 =͟͟͞͞(✹)`Д´)



Infinity - 無限大を表す

これはRayがわかりやすいと思います。こんなん。

if(Physics.Raycasat(ray, out hit, Mathf.Infinity) {}

無限大を取得できるので、この場合だとRayの長さが無限になります。

実際に使うときは長さを指定することが多いので、正直自分はあんま使わない変数だったり_(┐「ε:)_ズコー


NegativeInfinity - 負の無限大を表す

これは、Infinityの負のver.なんですが、なんかイメージしにくい。デバッグで見ると、コンソールには「-Infinity」と出ます。

まあ、正直使わんでしょ!(オイ


PI - 円周率( 3.14159265358979... )

こっちはもっと使わない!円周率???なにそれ食えんの!?!?!?

float perimeter = 2 * Mathf.PI * radius;

円周の長さは、半径×2×πで求められる例。使わん!


Abs(a) - 絶対値を返す

これは少し便利。マイナスの符号を取って、正の値を返してくれます。

Debug.Log(Mathf.Abs(-10.5);
// 結果 10.5


Approximately(float a, float b) - 2 つの Float 型の値を比較

使ったことないけど、便利そう。float型でしか使えないので注意。

if (Mathf.Approximately(a, b)) {
     Debug.Log("aとbは同じよーん");
}


Clamp(value, min, max) - 最大値と最小値の間で収める

これは便利!値を指定範囲で収めてくれます。int型でも使えます。

transform.position 
     = new Vector3(Mathf.Clamp(Time.time, 1.0F, 3.0F), 0, 0);

この例だと、コードが読み込まれてから1秒未満なら1、1〜3秒の間は1〜3の値、3秒以上経ったら3の値が返ってきます。

できるやつ(⌯꒪͒ ૢ∀ ૢ꒪͒)


Clamp01(float value) - 0 と 1 の間で収める

Clampの最小値と最大値がそれぞれ0と1に最初から指定されているver.です。もちflaot型オンリー。こいつも便利。


Ceil(float f) - 小数点以下を切り上げ

小数点以下を切り上げてくれます。(☝ ՞ਊ ՞)☝アゲアゲ

 Debug.Log(Mathf.Ceil(10.0F));
// 結果 10
Debug.Log(Mathf.Ceil(10.2F));
// 結果 11
Debug.Log(Mathf.Ceil(10.7F));
// 結果 11
Debug.Log(Mathf.Ceil(-10.0F));
// 結果 -10
Debug.Log(Mathf.Ceil(-10.2F));
// 結果 -10
Debug.Log(Mathf.Ceil(-10.7F));
// 結果 -10

*Ceil関数はたとえ 10.0f でもfloat型のまま10を返しますが、CeilToInt関数を使うと 10.0f はint型の10を返します。つまりCeilToInt関数の場合、計算結果の値はint型に変換されます。


Floor(float f) - 小数点以下を切捨て

Ceilの逆バージョン。10.2なら10が、-10.2なら-11が返ってきます。これも返された値をint型に変換する、FloorToInt関数があります。


Lerp(float from, float to, float t) - tの値によってfromからtoまでの中間値を取得

第三引数 t の値が0のとき from の値が、1のとき to の値が得られます。なので、t が0.5のときは from と to の丁度中間の値が得られます。

float min = 10.0F;
float max = 20.0F;
void Update() {
     transform.position 
          = new Vector3(Mathf.Lerp(min, max,
                     Time.time), 0, 0);
}

値間の補正によく使います。滅茶苦茶できるやつ!多分使用頻度No.1!使い始めればきっと貴方もこの子無しには生きられない身体に・・・


LerpAngle(float a, float b, float t) - 角度で使うLerp

角度を計算するときに使うならこっちのLerpAngleを使いましょう。

360度で一回転することを考えて良い感じに計算してくれます。

float minAngle = 0.0F;
float maxAngle = 90.0F;
void Update() {
     float angle 
       = Mathf.LerpAngle(minAngle, maxAngle, Time.time);
     transform.eulerAngles = new Vector3(0, angle, 0);
}


MoveTowards(float current, float target, float maxDelta) - current 引数から target 引数まで、maxDelta 引数のスピードで移動

すごく便利そうだけど、調べるまで知らなかったので今まで使ったことのない子。優秀感が漂います・・・!

float currStrength;
float maxStrength;
float recoveryRate;
void Update() {
     currStrength 
       = Mathf.MoveTowards(currStrength, maxStrength, 
                     recoveryRate * Time.deltaTime);
}


MoveTowardsAngle(float current, float target, float maxDelta) - current 引数から target 引数まで、maxDelta 引数のスピードで移動

MoveTowards関数の角度計算向けver.です。

float target = 270.0F;
float speed = 45.0F;
void Update() {
     float angle 
       = Mathf.MoveTowardsAngle(transform.eulerAngles.y,
                     target, speed * Time.deltaTime);
     transform.eulerAngles = new Vector3(0, angle, 0);
}


PingPong(float t, float length) - 0とlengthの間の値を得る

この関数はその名前の通り、ピンポン球のように0と第二引数 length の値の間を、第一引数 t の値を参照して行ったり来たりします。

Debug.Log(Mathf.PingPong(0, 3);
// 結果 0
Debug.Log(Mathf.PingPong(3, 3);
// 結果 3
Debug.Log(Mathf.PingPong(4, 3);
// 結果 2
Debug.Log(Mathf.PingPong(6, 3);
// 結果 0

よく使うパターンが、Time.timeを第一引数に入れるやつです。

transform.position 
     = new Vector3(Mathf.PingPong(Time.time, 10), 0, 0);


Round(float f) - f の値に一番近いint型の値を得る

10.2なら10を、10.7なら11を返します。.5で終わる値の場合、偶数の方の整数を得ます。例えば10.5なら10、11.5なら12といった感じです。

最近これを使ってグリッドベースの移動を再現できました。ポケモンみたいな感じの移動。

これにもRoundToInt関数があります。


SmoothDamp
(float current, float target, ref float currentVelocity, float smoothTime, float maxSpeed = Mathf.Infinity, float deltaTime = Time.deltaTime)
- current から target まで、smoothTimeでスムージング

maxSpeedを指定しなければMath.Infinity、deltaTimeを指定しなければTime.deltaTimeが入ります。

ちょっとややこしいですが、すごく便利な関数です。めちゃくちゃ使います。

例えば、目的のオブジェクトを今の位置から、y 10の位置に1秒かけてスムーズに移動させたいときは、

float yVelocity = 0.0F;
void Update() {
     float newPosition 
        = Mathf.SmoothDamp(transform.position.y, 
                10, ref yVelocity, 1);
     transform.position
        = new Vector3(transform.position.x, 
                newPosition, transform.position.z);
}

てな感じです。第三引数の currentVelocity は適当に入れておけばオッケーです。


SmoothDampAngle
(float current, float target, ref float currentVelocity, float smoothTime, float maxSpeed = Mathf.Infinity, float deltaTime = Time.deltaTime)
- 角度ver.

角度計算のときにはこっちを使いましょう。


Sin(float f) - サイン

Cos(float f) - コサイン

Tan(float f) - タンジェント

三角比でお馴染みの文系殺し三人衆です。自分もあまり使うことはないのですが、紹介しないで終わったら怒られそうなので・・・(誰にだ)

Tan関数にいたっては全く使ったことがないのですが、Sin、Cos関数は、カメラをプレイヤーの周りを回るようにしたかったときに使いました。

こんな感じ。

float rotateAngle = 0f;
float radius = 5.0f;
float height = 10.0f;
void Upate() {
    cameraTransform.position
       = new Vector3(
             playerTf.position.x + Mathf.Sin(rotateAngle) * radius,
             height, 
             playerTf.position.z + Mathf.Cos(rotateAngle) * radius);
    rotateAngle += .03f;
}

解説は面倒くさいので紹介するだけにとどめます( ´ิ(ꈊ) ´ิ)ウェイ


少し長くなってお腹が減ったのでMathfクラスの紹介は以上にします'(<◉>◞౪◟<◉>)'

「へ〜こんなのあるんだー」といった感じで頭の片隅にでも入れていただければ、空腹に耐えてキーボードを叩いた甲斐があります(・:゚д゚:・)ハァハァ

意外と便利なMathfクラス、これで貴方もエリートプログラマー!?!?!?(エリートってなんだ)