【Unity】Freeze PositionでRigidbodyによる特定の軸への移動を制御できる

Freeze Positionとは? Unity

こんにちは、ともくんのゲーム作り部屋にようこそ!

このページでは、

「RigidbodyのFreeze Positionってなに?」

「Freeze Positionでどんなことができるの?」

というお悩みの方に向けた内容となっています。

Unityでオブジェクトに物理的挙動を加えられるRigidbodyコンポーネントでは、Freeze Positionという機能を使うことができます。

このFreeze Positionとは、オブジェクトが物理的挙動で移動した際に、特定の軸における移動を防ぐことができる機能になっています。

例えば、オブジェクトに力を加えた際に、上に浮かせたくないといった場合などに使用します。

そこで、このページでは、UnityのRigidbodyコンポーネントにあるFreeze Positionという機能について、どんな機能なのか、また使い方までをまとめていきます。

この記事を書いた人

ゲーム作りを学び始めた一児のパパです。
このブログは、子供から「ゲームを作ってみたい!」と言われ、非プログラマーでゲーム作りをしたことない僕が、ゲーム作りの本を読んで独学でゲーム開発を学んでいるブログです。
同じように初めてゲーム作りをしている方と一緒に学んでいけるようなブログに出来たらいいなと思っています。
また、「このコードはおかしい」とか「もっと良い書き方があるよ!」などあれば、どんどん指摘して頂けると助かります。

Freeze Positionとは?Rigidbodyによる移動を制御できる機能

まずは、Freeze Positionがどういうものなのかを紹介していきます。

Freeze Positionとは、Rigidbodyコンポーネントが付いているオブジェクトに対して、特定の軸における移動を防止することができる機能です。

Rigidbodyを付けたオブジェクトは、AddForceメソッドなどを使って力を加えて移動させることができますが、想定していない動きになってしまうことがあり、その際にFreeze Positionを使うことで移動を制御することができます。

例えば、以下のようにオブジェクトに力を加えて移動させようとした際に、オブジェクトが浮いてしまうということがあります。

オブジェクトは移動させたいけど、宙に浮かせたくないというような場合に、Freeze PositionでY軸への移動を防止するようにしてあげます。

すると、上記のようにオブジェクトを浮かせずに、移動させることができるようになります。

Freeze Positionの使い方

ここからは、Freeze Positionの使い方について紹介していきます。

インスペクターウィンドウから設定する

Freeze Positionを設定する場合は、オブジェクトを選択してインスペクターウィンドウから、RigidbodyコンポーネントのConstraintsの中にあるFreeze Positionで設定していきます。

具体的には、

  • X軸の移動を防止するならFreeze Position Xにチェック
  • Y軸の移動を防止するならFreeze Position Yにチェック
  • Z軸の移動を防止するならFreeze Position Zにチェック

というように、オブジェクトの移動を防止したい軸をチェックすることで、その軸の移動を防ぐことができます。

例えば、Rigidbodyを付けた赤い球形のオブジェクトに、青いキューブオブジェクトを衝突させて動かしているとします。

この衝突させられている赤いオブジェクトのFreeze PositionのXにチェックを入れると、衝突した後のX軸への移動が防止され、Z軸側に向かって移動するようになります。

また、Freeze PositionのZにチェックを入れると、Z軸の移動を防止することができ、X軸側に移動するという全く異なる挙動を作ることができます。

なお、2Dゲームで使うRigidbody2Dでは、Freeze Positionで指定できる軸はXとYだけとなっています。

スクリプトから設定する

Freeze Positionの設定は、インスペクターウィンドウからだけでなくスクリプトから設定することもできます。

なお、スクリプトから設定する場合は先にRigidbodyコンポーネントをGetComponentメソッドなどで取得しておく必要があります。

Freeze PositionのXを設定する

スクリプトからFreeze PositionのXを設定したい場合は、

Rigidbody.constraints = RigidbodyConstraints.FreezePositionX;

もしくは、

Rigidbody2D.constraints = RigidbodyConstraints2D.FreezePositionX;

と記述していきます。

例えば、

using UnityEngine;

public class Test1 : MonoBehaviour
{
    Rigidbody rb;   // Rigidbody型の変数を宣言

    void Start()
    {
        rb = GetComponent<Rigidbody>(); // Rigidbodyコンポーネントを取得
        rb.constraints = RigidbodyConstraints.FreezePositionX;  // FreezePositionのXを設定する
    }
}

上記のように、Startメソッドの中の10行目で処理を記述しておくことで、ゲームを実行したタイミングで、Freeze PositionのXが設定されているのが分かります。

<ゲーム実行前>

<ゲーム実行後>

Freeze PositionのYを設定する

スクリプトからFreeze PositionのYを設定したい場合は、

Rigidbody.constraints = RigidbodyConstraints.FreezePositionY;

もしくは、

Rigidbody2D.constraints = RigidbodyConstraints2D.FreezePositionY;

と記述していきます。

例えば、スペースキーを押してFreeze PositionのYを設定する処理を作る場合、

using UnityEngine;

public class Test : MonoBehaviour
{
    Rigidbody2D rb; // Rigidbody型の変数を宣言

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();   // Rigidbodyコンポーネントを取得
    }

    void Update()
    {
        // スペースキーを押した場合
        if (Input.GetKeyDown(KeyCode.Space))
        {
            rb.constraints = RigidbodyConstraints2D.FreezePositionY;    // FreezePositionのYを設定する
        }
    }
}

上記のように、17行目で処理を記述しておくことで、スペースキーを押したらY軸の移動が防止されるようになります。

これを使えば、以下のようにオブジェクトが地面で跳ねている途中の段階で動きを止めるといったこともできるようになります。

Freeze PositionのZを設定する

スクリプトからFreeze PositionのZを設定したい場合は、

Rigidbody.constraints = RigidbodyConstraints.FreezePositionZ;

もしくは、

Rigidbody2D.constraints = RigidbodyConstraints2D.FreezePositionZ;

と記述していきます。

例えば、特定のオブジェクトと衝突したら、Freeze Position Zを設定したいというような場合は、

using UnityEngine;

public class Test : MonoBehaviour
{
    Rigidbody rb;   // Rigidbody型の変数を宣言
    public GameObject target;   // ターゲットとなるオブジェクトを取得

    void Start()
    {
        rb = GetComponent<Rigidbody>(); // Rigidbodyコンポーネントを取得
        rb.AddForce((target.transform.position - this.transform.position) * 150f);  // ターゲットに向かって力を加える
    }

    void OnCollisionEnter(Collision collision)
    {
        // ターゲットに衝突した場合
        if (collision.gameObject == target)
        {
            rb.constraints = RigidbodyConstraints.FreezePositionZ;  // FreezePositionのZを設定する
        }
    }
}

上記のように、衝突したことを検知するOnCollisionメソッド内の19行目で処理を記述しておくことで、衝突前はZ軸へ移動していた青いオブジェクトが、衝突後はX軸にだけ移動しているのが分かります。

Freeze Positionの全ての軸を設定する

Freeze Positionの全ての軸をスクリプトから設定することもできます。

その場合は、

Rigidbody.constraints = RigidbodyConstraints.FreezePosition;

もしくは、

Rigidbody2D.constraints = RigidbodyConstraints2D.FreezePosition;

例えば、以下のスクリプトをオブジェクトにアタッチしておきます。

using UnityEngine;

public class Test : MonoBehaviour
{
    Rigidbody rb;   // Rigidbody型の変数を宣言

    void Start()
    {
        rb = GetComponent<Rigidbody>(); // Rigidbodyコンポーネントを取得
        rb.constraints = RigidbodyConstraints.FreezePosition;   // 全ての軸のFreezePositionを設定する
    }
}

Startメソッド内の10行目で、全てのFreeze Positionを設定することで、ゲーム実行時に処理が実行されて、全ての軸への移動が防止されているのが分かります。

<ゲーム実行前>

<ゲーム実行後>

Freeze Positionの設定を解除する

スクリプトからFreeze Positionの設定を解除する場合は、

Rigidbody.constraints = RigidbodyConstraints.None;

もしくは、

Rigidbody2D.constraints = RigidbodyConstraints2D.None;

と記述することで解除できます。

ただし、constraintsの中の設定を全て解除することになるため、全ての軸のFreeze Positionの設定が解除されて、また回転を防止することができるFreeze Rotationの設定も解除されることになります。

例えば、スペースキーを押したらFreeze Positionの設定を全て解除するという処理を作る場合、

using UnityEngine;

public class Test : MonoBehaviour
{
    Rigidbody rb;   // Rigidbody型の変数を宣言

    void Start()
    {
        rb = GetComponent<Rigidbody>(); // Rigidbodyコンポーネントを取得
    }

    void Update()
    {
        // スペースキーを押した場合
        if (Input.GetKeyDown(KeyCode.Space))
        {
            rb.constraints = RigidbodyConstraints.None;   // Constraintsの設定を全て無しにする
        }
    }
}

17行目のように記述してあげることで、Freeze Positionの設定を解除することができます。

まとめ

このページでは、UnityのRigidbodyコンポーネントで使えるFreeze Positionという機能について、どういうものなのか、また使い方までをまとめていきましたが、いかがでしたでしょうか?

Freeze Positionとは、Rigidbodyの付いたオブジェクトが移動される際に、特定の軸における移動を防止することができる設定です。

このFreeze Positionを使うことで、Rigidbodyのオブジェクトが想定していない動きや移動をしないように制御することができます。

Freeze Positionを設定する際は、インスペクターウィンドウから設定するか、スクリプト内で記述することで、特定のタイミングでFreeze Positionの設定を行うことができます。

最後までお読みいただきまして、ありがとうございました!

コメント