Unityにおいて、オブジェクトのY方向(上下方向)に力を加える方法を教えてください。特に以下の点について知りたいです:
こんにちは!UnityでのY方向への力の適用方法について、実践的な観点から説明します。
Unityでは主にRigidbodyコンポーネントを持つオブジェクトに対して力を加えることができます。Y方向(通常は上方向)への力の適用の基本的な方法は以下の通りです:
using UnityEngine;
public class ForceApplier : MonoBehaviour
{
    // インスペクターで設定できるパラメータ
    [SerializeField] private float forceAmount = 10f;
    // コンポーネント参照
    private Rigidbody rb;
    void Start()
    {
        // Rigidbodyコンポーネントの取得
        rb = GetComponent<Rigidbody>();
    }
    void Update()
    {
        // 例:スペースキーを押したときにY方向に力を加える
        if (Input.GetKeyDown(KeyCode.Space))
        {
            ApplyYForce();
        }
    }
    void ApplyYForce()
    {
        // 方法1: 座標を直接指定
        rb.AddForce(0, forceAmount, 0);
        // 方法2: Vector3.upを使用
        // rb.AddForce(Vector3.up * forceAmount);
    }
}
Unityでは力を加える際の挙動を制御する4つのForceModeが用意されています:
// 継続的な力を加える (F = ma) - デフォルト
rb.AddForce(Vector3.up * forceAmount, ForceMode.Force);
// 瞬間的な力(インパルス)を加える
rb.AddForce(Vector3.up * forceAmount, ForceMode.Impulse);
// 質量を無視して加速度として適用
rb.AddForce(Vector3.up * forceAmount, ForceMode.Acceleration);
// 質量を無視して速度変化として適用
rb.AddForce(Vector3.up * forceAmount, ForceMode.VelocityChange);
各モードの特徴と使い分け:
ForceMode.Force
ForceMode.Impulse
ForceMode.Acceleration
ForceMode.VelocityChange
using UnityEngine;
public class CharacterJump : MonoBehaviour
{
    [SerializeField] private float jumpForce = 5f;
    [SerializeField] private Transform groundCheck;
    [SerializeField] private float groundCheckRadius = 0.2f;
    [SerializeField] private LayerMask groundLayer;
    private Rigidbody rb;
    private bool isGrounded;
    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }
    void Update()
    {
        // 地面との接触を判定
        isGrounded = Physics.CheckSphere(groundCheck.position, groundCheckRadius, groundLayer);
        // ジャンプ入力
        if (Input.GetKeyDown(KeyCode.Space) && isGrounded)
        {
            Jump();
        }
    }
    void Jump()
    {
        // ジャンプにはImpulseモードが適している
        rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
    }
}
using UnityEngine;
public class BuoyancyEffect : MonoBehaviour
{
    [SerializeField] private float volume = 1.0f;
    [SerializeField] private float waterDensity = 1.0f;
    [SerializeField] private Transform waterSurfaceCheck;
    private Rigidbody rb;
    private bool isUnderwater;
    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }
    void FixedUpdate()
    {
        // 水中判定
        isUnderwater = waterSurfaceCheck.position.y < 0; // 0を水面の高さに置き換え
        if (isUnderwater)
        {
            // アルキメデスの原理に基づく浮力
            float buoyancyForce = volume * waterDensity * Physics.gravity.magnitude;
            rb.AddForce(Vector3.up * buoyancyForce);
        }
    }
}
using UnityEngine;
public class WindLiftEffect : MonoBehaviour
{
    [SerializeField] private float windStrength = 2.0f;
    [SerializeField] private float maxWindEffect = 10.0f;
    [SerializeField] private AnimationCurve windCurve;
    private Rigidbody rb;
    private float currentWindTime = 0f;
    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }
    void FixedUpdate()
    {
        // 時間経過に基づく風の強さの変化
        currentWindTime += Time.fixedDeltaTime;
        float windEffect = windCurve.Evaluate(Mathf.PingPong(currentWindTime, 1.0f)) * maxWindEffect;
        // Y方向に風力を適用
        rb.AddForce(Vector3.up * windStrength * windEffect);
    }
}
AddForceの代わりに、直接速度を設定することもできます:
void SetYVelocity(float yVelocity)
{
    // 現在のX, Z速度を維持しつつ、Y速度のみを変更
    rb.velocity = new Vector3(rb.velocity.x, yVelocity, rb.velocity.z);
}
これは即時的な速度変更が必要な場合(例:二段ジャンプ、速度のリセットなど)に有効です。
UpdateではなくFixedUpdate内に実装するのが適切ですこの回答は、Unity 2022.3 LTS を基準に作成されています。新しいバージョンでは仕様が変更されている可能性があるため、適宜公式ドキュメントを参照してください。