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 を基準に作成されています。新しいバージョンでは仕様が変更されている可能性があるため、適宜公式ドキュメントを参照してください。