単純な物理

ゲームでよく使われそうな物理を練習しましょう。以下の処理は、Unity の Rigidbody を対応してくれる処理である。

移動、速度、加速度

移動と速度の関係性

 次の状況を考えてみてください:あるキャラクターは2D空間の位置「p = (px, py)」にいる。このキャラクターは定めた時間「Δt」をかけて、ある目的地「q = (qx, qy)」に到着させたい。

image.png

 この場合は、移動に必要な速度「v = (vx, vy)」を求めることができる:

image.png

始点「p」から終点「q」までの距離(と向き)を到着までの必要な時間で割ると、速度「v」を求める。それでは、始点「p」と速度「v」があれば、定めた時間「t」の後に、どこにいるか知りたいなら:

image.png

Unityでは、フレーム間の時間を「Time.deltaTime」で取得できるので、移動を計算したいなら:

// 始点(現在の位置)
Vector3 p = transform.position;

// vは「Vector3」型の速度(量と向き)
Vector3 q = p + v * Time.deltaTime;

// 位置を更新
transform.position = q;

練習

シーンに何かの3Dオブジェクトを追加。スペースキーを押したら、一定速度で移動する。キーを放したら、速度を0にする。速度を Inspectorで設定できるようにしてください。

TestVelocityのスクリプト
// 物理の練習:一定速度で移動
public class TestVelocity : MonoBehaviour
{
    // 速度ベクトル(量+向き)
    [SerializeField]
    private Vector3 velocity; 

    void Update()
    {
        // まず、速度はゼロにする
        Vector3 v = Vector3.zero;

        // 何かのキーを押したら
        if (Input.GetKey(KeyCode.Space))
            v = velocity; // 速度を書き換える

        // 物理演算を使って、移動する
        Vector3 p = transform.position;

        // 移動の式
        Vector3 q = p + v * Time.deltaTime; 

        // 位置更新
        transform.position = q;
    }
}

 

加速度

 速度は「時間単位当たりの物体の位置の変化量」であるとしたら、加速度は「時間単位当たりの物体の速度の変化量」である(速度の速度)。つまり:

image.png

速度「v」は、初期速度「v0」に加速度「a」と加速した時間「Δt」の乗算を足す。Unityで実装するなら:

// 内部の速度ベクトル
private Vector3 velocity;

private void Update()
{
	// 初期速度
	Vector3 v0 = velocity;

	// 新しい速度を計算
	Vector3 v = v0 + a * Time.deltaTime

	// 次のフレームの初期速度を更新
	velocity = v;
}

練習

加速度を試せる TestAccel のスクリプトを作成してください。「A」キーを押したら一定加速度で移動する。「S」キーを押すと一定速度で減速する。速度が0以下にならないようにする。なお、加速度を Inspectorで設定できるようにしてください。

TestAccelのスクリプト
// 物理の練習:加速度
public class TestAccel : MonoBehaviour
{
	[SerializeField]
	Vector3 acceleration; // 加速度ベクトル(量+向き)

	Vector3 velocity; // 速度(内部)

	void Update()
	{
		// まずは、速度を更新
		Vector3 a = Vector3.zero; // 加速なし
		
		// 「a」を押したら、加速
		if (Input.GetKey(KeyCode.A))
			a = acceleration;
		
		// 「s」を押したら、減速
		else if (Input.GetKey(KeyCode.S))
			a = -acceleration;

		// 現在の速度
		velocity = velocity + a * Time.deltaTime;

		// 位置を更新(移動)
		Vector3 p = transform.position;
		Vector3 q = p + velocity * Time.deltaTime;
		transform.position = q;
	}
}

重力

重力は下に向かう加速度ベクトルである。地球の場合は、おおよそ 9.81 m/s2 である。

// 重力ベクトル
Vector3 gravity = new Vector3(0, -9.81f, 0);

練習

ボールを投げるスクリプト「ThrowBall」を作成する。Inspectorでボールに初期速度を設定し、斜め上に投げ、重力で落とす。無限に落ちないように、Y軸の位置は0以下にならないようにする。

image.png

v0 の初期速度にてボールを投げる。

g 重力の加速度であり、時間により落下してくる。

ThrowBall スクリプト
// ボールを投げ、重力で落とす
public class ThrowBall : MonoBehaviour
{
    // ボールの初期速度
    [SerializeField] 
    private Vector3 velocity;

    private void Update()
    {
        // 重力による加速度を使い、速度を更新
        Vector3 gravity = new Vector3(0, -9.81f, 0);
        velocity += gravity * Time.deltaTime;
        
        // 位置を更新
        var position = transform.position;
        position += velocity * Time.deltaTime;
        
        // 高さが0以下にならないようにする
        position.y = Mathf.Max(0, position.y);
        transform.position = position;
    }
}

質量、力と加速度の関係性

すべての物体は「質量」があり、重ければ重いほど動かすのは力が必要。従って、物体の加速度は、物体の重さ(質量)と力に依存する。その関係性以下の通りである:

image.png

ここで、「a」は加速度であり、「f」は力、「m」は質量である。これは「Rigidbody.AddForce」の処理である。

練習

ThrowBall を更新し、ボールに質量を与え、キーを押したら力を与える。力のベクトルと質量をInspectorで変えられるようにする。

image.png

m はボールの質量である。

f は投げる力である。

g 重力の加速度であり、時間により落下してくる。

ThrowBall スクリプト
// ボールを投げ、重力で落とす
public class ThrowBall : MonoBehaviour
{
    // ボールの質量
    [SerializeField] 
    private float mass;

    // 投げる力
    [SerializeField] 
    private Vector3 force;
    
    // 速度(内部)
    private Vector3 velocity;

    private void Start()
    {
        // 力と質量から加速度を計算
        Vector3 a = force / mass;
        
        // 加速度は時間をかけて速度を変える
        // 投げる時間を 0.5秒にしましょう
        velocity = a * 0.5f;
    }

    private void Update()
    {
        // 重力による加速度を使い、速度を更新
        Vector3 gravity = new Vector3(0, -9.81f, 0);
        velocity += gravity * Time.deltaTime;
        
        // 位置を更新
        var position = transform.position;
        position += velocity * Time.deltaTime;
        
        // 高さが0以下にならないようにする
        position.y = Mathf.Max(0, position.y);
        transform.position = position;
    }
}

Revision #2
Created 2026-06-23 07:01:51 UTC by Menendez Francisco
Updated 2026-06-24 01:22:20 UTC by Menendez Francisco