Unityでオブジェクトを回転させる方法完全ガイド

unity

「Unityでオブジェクトを回転させたいけど、どうすればいいの?」
「スクリプトでの回転制御がうまくいかない」
そんな悩みを持つUnity初心者の方は多いのではないでしょうか。

この記事では、Unityでオブジェクトを回転させる方法を、基礎から応用まで詳しく解説します。

インスペクター操作から始まり、C#スクリプトでの動的制御まで、実際のコード例とともにわかりやすく説明します。

2D・3D両方の環境に対応した内容で、初心者でも安心して学習できます。

スポンサーリンク

Unityの回転システムについて

回転の基本概念

Unityでは、オブジェクトの回転はTransform コンポーネントの Rotationで管理されています。

この仕組みを理解することで、思い通りの回転制御ができるようになります。

座標軸と回転方向

3D空間での回転軸

  • X軸回転(Pitch):前後に傾ける動き(うなずき)
  • Y軸回転(Yaw):左右に向きを変える動き(首振り)
  • Z軸回転(Roll):時計・反時計回りの動き(ひねり)

2D空間での回転

  • 主にZ軸回転のみを使用
  • X軸とY軸の回転は通常使わない

オイラー角とクォータニオン

オイラー角(Euler Angles)

  • 人間が理解しやすい:X、Y、Zの角度で表現
  • インスペクターで表示される形式
  • ジンバルロックという問題が起こる場合がある

クォータニオン(Quaternion)

  • Unityが内部で使用する回転表現
  • **4つの数値(x, y, z, w)**で構成
  • ジンバルロックが起こらない
  • 直感的ではないが、計算に優れている

なぜこの仕組みを理解すべきか?

回転制御の精度向上

  • 適切な方法を選択できる
  • 予期しない動作を避けられる
  • パフォーマンスの最適化

トラブルシューティング

  • 回転がおかしい時の原因を特定
  • より複雑な回転アニメーションの実装
  • 他の開発者とのコミュニケーション

インスペクターでの回転設定

プログラミングが苦手な方でも、Unityエディタの操作だけで簡単にオブジェクトを回転させることができます。

基本的な手動回転

手順1:オブジェクトの選択

  1. HierarchyまたはSceneビューでオブジェクトを選択
  2. Inspectorウィンドウが更新されることを確認

手順2:Transform コンポーネントの確認

  1. Inspector の上部にあるTransformコンポーネントを見つける
  2. PositionRotationScaleの3つの項目があることを確認

手順3:回転値の設定

  1. Rotationの欄を見つける
  2. X、Y、Zの値を直接入力
  3. Enterキーを押すか他の場所をクリックして適用

実際の例

Rotation:
X: 0    (X軸回転なし)
Y: 45   (Y軸を45度回転)
Z: 0    (Z軸回転なし)

Scene ビューでの直感的な回転

回転ツールの使用

  1. オブジェクトを選択
  2. **ツールバーの回転ツール(E キー)**をクリック
  3. Scene ビューでオブジェクトの周りに色付きの円が表示される
  4. 赤い円(X軸)緑の円(Y軸)、**青い円(Z軸)**をドラッグして回転

ツールの色分け

  • 赤色:X軸方向の回転
  • 緑色:Y軸方向の回転
  • 青色:Z軸方向の回転
  • 灰色の外円:カメラ視点に対する回転

アニメーションウィンドウでの回転

キーフレームアニメーションの作成

  1. オブジェクトを選択
  2. WindowAnimationAnimationでアニメーションウィンドウを開く
  3. Createボタンでアニメーションファイルを作成
  4. Add PropertyTransformRotationを追加
  5. タイムライン上でキーフレームを設定

回転アニメーションの例

0秒地点: Rotation Y = 0度
1秒地点: Rotation Y = 180度
2秒地点: Rotation Y = 360度

注意点とコツ

角度の範囲

  • 0〜360度または**-180〜180度**で表示される
  • 360度 = 0度(同じ向き)
  • -90度 = 270度(同じ向き)

値のリセット方法

  • Transform コンポーネントの歯車アイコンReset
  • または、Rotationの値を0, 0, 0に手動設定

C#スクリプトでの回転制御

スクリプトを使うことで、時間経過や条件に応じて動的にオブジェクトを回転させることができます。

基本的な回転スクリプト

常に回転し続けるオブジェクト

using UnityEngine;

public class ContinuousRotation : MonoBehaviour
{
    [Header("回転設定")]
    public Vector3 rotationSpeed = new Vector3(0, 90, 0); // 1秒間の回転角度
    
    void Update()
    {
        // 毎フレーム少しずつ回転
        transform.Rotate(rotationSpeed * Time.deltaTime);
    }
}

使用方法

  1. 空のGameObjectを作成
  2. 上記スクリプトをアタッチ
  3. Inspector でRotation Speedを調整
  4. 再生ボタンを押して動作確認

滑らかな回転制御

指定角度まで滑らかに回転

using UnityEngine;

public class SmoothRotation : MonoBehaviour
{
    [Header("回転設定")]
    public Vector3 targetRotation = new Vector3(0, 90, 0); // 目標角度
    public float rotationSpeed = 2.0f; // 回転速度(倍率)
    
    private Vector3 initialRotation; // 初期角度
    private bool isRotating = false;
    
    void Start()
    {
        initialRotation = transform.eulerAngles;
    }
    
    void Update()
    {
        // スペースキーで回転開始
        if (Input.GetKeyDown(KeyCode.Space))
        {
            isRotating = !isRotating;
        }
        
        if (isRotating)
        {
            // 目標角度まで滑らかに回転
            Vector3 targetEuler = initialRotation + targetRotation;
            Quaternion targetQuaternion = Quaternion.Euler(targetEuler);
            
            transform.rotation = Quaternion.Slerp(
                transform.rotation,
                targetQuaternion,
                rotationSpeed * Time.deltaTime
            );
        }
    }
}

特定の対象を向く回転

プレイヤーや他のオブジェクトの方向を向く

using UnityEngine;

public class LookAtTarget : MonoBehaviour
{
    [Header("ターゲット設定")]
    public Transform target; // 向かせたい対象
    public float rotationSpeed = 2.0f; // 回転速度
    public bool lookAtY = true; // Y軸回転のみか
    
    void Update()
    {
        if (target != null)
        {
            // ターゲットの方向を計算
            Vector3 direction = target.position - transform.position;
            
            // Y軸回転のみの場合
            if (lookAtY)
            {
                direction.y = 0; // Y成分を無視
            }
            
            // 方向が有効な場合のみ回転
            if (direction != Vector3.zero)
            {
                Quaternion targetRotation = Quaternion.LookRotation(direction);
                
                // 滑らかに回転
                transform.rotation = Quaternion.Slerp(
                    transform.rotation,
                    targetRotation,
                    rotationSpeed * Time.deltaTime
                );
            }
        }
    }
}

マウス操作での回転制御

マウスドラッグでオブジェクトを回転

using UnityEngine;

public class MouseRotation : MonoBehaviour
{
    [Header("マウス回転設定")]
    public float sensitivity = 100.0f; // 感度
    public bool invertY = false; // Y軸を反転するか
    
    private bool isDragging = false;
    private Vector3 lastMousePosition;
    
    void Update()
    {
        // マウスボタンが押されたとき
        if (Input.GetMouseButtonDown(0))
        {
            isDragging = true;
            lastMousePosition = Input.mousePosition;
        }
        
        // マウスボタンが離されたとき
        if (Input.GetMouseButtonUp(0))
        {
            isDragging = false;
        }
        
        // ドラッグ中の回転処理
        if (isDragging)
        {
            Vector3 mouseDelta = Input.mousePosition - lastMousePosition;
            
            // マウスの移動量を回転角度に変換
            float rotationY = mouseDelta.x * sensitivity * Time.deltaTime;
            float rotationX = mouseDelta.y * sensitivity * Time.deltaTime;
            
            if (invertY)
            {
                rotationX = -rotationX;
            }
            
            // オブジェクトを回転
            transform.Rotate(-rotationX, rotationY, 0, Space.World);
            
            lastMousePosition = Input.mousePosition;
        }
    }
}

回転の応用テクニック

より高度な回転制御を実現するためのテクニックを紹介します。

アニメーションカーブを使った回転

カスタムカーブで自然な動きを実現

using UnityEngine;

public class CurveRotation : MonoBehaviour
{
    [Header("アニメーションカーブ")]
    public AnimationCurve rotationCurve = AnimationCurve.EaseInOut(0, 0, 1, 360);
    public float animationDuration = 2.0f; // アニメーション時間
    
    private float currentTime = 0.0f;
    private bool isAnimating = false;
    private Vector3 initialRotation;
    
    void Start()
    {
        initialRotation = transform.eulerAngles;
    }
    
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            StartRotation();
        }
        
        if (isAnimating)
        {
            currentTime += Time.deltaTime;
            
            // アニメーション進行度(0〜1)
            float progress = currentTime / animationDuration;
            
            if (progress >= 1.0f)
            {
                progress = 1.0f;
                isAnimating = false;
            }
            
            // カーブから回転角度を取得
            float curveValue = rotationCurve.Evaluate(progress);
            
            // Y軸回転を適用
            Vector3 newRotation = initialRotation;
            newRotation.y += curveValue;
            transform.eulerAngles = newRotation;
        }
    }
    
    public void StartRotation()
    {
        currentTime = 0.0f;
        isAnimating = true;
        initialRotation = transform.eulerAngles;
    }
}

複数軸の同時回転

複雑な回転パターンの実装

using UnityEngine;

public class MultiAxisRotation : MonoBehaviour
{
    [Header("複数軸回転設定")]
    public Vector3 primaryRotation = new Vector3(0, 90, 0); // 主回転
    public Vector3 secondaryRotation = new Vector3(45, 0, 0); // 副回転
    public float primarySpeed = 1.0f; // 主回転速度
    public float secondarySpeed = 0.5f; // 副回転速度
    
    private Transform primaryPivot; // 主回転用の親オブジェクト
    private Transform secondaryPivot; // 副回転用の親オブジェクト
    
    void Start()
    {
        SetupPivots();
    }
    
    void SetupPivots()
    {
        // 主回転用の空オブジェクト
        GameObject primaryGO = new GameObject("Primary Pivot");
        primaryGO.transform.position = transform.position;
        primaryPivot = primaryGO.transform;
        
        // 副回転用の空オブジェクト
        GameObject secondaryGO = new GameObject("Secondary Pivot");
        secondaryGO.transform.position = transform.position;
        secondaryGO.transform.SetParent(primaryPivot);
        secondaryPivot = secondaryGO.transform;
        
        // このオブジェクトを副回転の子に
        transform.SetParent(secondaryPivot);
    }
    
    void Update()
    {
        // 主回転(Y軸中心)
        primaryPivot.Rotate(primaryRotation * primarySpeed * Time.deltaTime);
        
        // 副回転(X軸中心)
        secondaryPivot.Rotate(secondaryRotation * secondarySpeed * Time.deltaTime);
    }
}

物理的な回転制御

Rigidbodyを使った物理的な回転

using UnityEngine;

public class PhysicsRotation : MonoBehaviour
{
    [Header("物理回転設定")]
    public float torqueForce = 10.0f; // 回転力
    public Vector3 torqueAxis = Vector3.up; // 回転軸
    
    private Rigidbody rb;
    
    void Start()
    {
        rb = GetComponent<Rigidbody>();
        if (rb == null)
        {
            rb = gameObject.AddComponent<Rigidbody>();
        }
    }
    
    void Update()
    {
        // 入力による回転制御
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");
        
        // トルクを適用
        Vector3 torque = Vector3.zero;
        torque.y = horizontal * torqueForce; // 左右回転
        torque.x = vertical * torqueForce;   // 前後回転
        
        rb.AddTorque(torque);
    }
    
    void FixedUpdate()
    {
        // 回転速度の制限
        if (rb.angularVelocity.magnitude > 10.0f)
        {
            rb.angularVelocity = rb.angularVelocity.normalized * 10.0f;
        }
    }
}

2D環境での回転制御

2Dゲームでの回転制御には特別な考慮事項があります。

2D回転の基本

Z軸回転のみを使用

using UnityEngine;

public class Rotation2D : MonoBehaviour
{
    [Header("2D回転設定")]
    public float rotationSpeed = 90.0f; // 度/秒
    public bool autoRotate = false; // 自動回転
    
    void Update()
    {
        if (autoRotate)
        {
            // Z軸を中心に連続回転
            transform.Rotate(0, 0, rotationSpeed * Time.deltaTime);
        }
        
        // キー入力による回転
        if (Input.GetKey(KeyCode.Q))
        {
            transform.Rotate(0, 0, rotationSpeed * Time.deltaTime);
        }
        if (Input.GetKey(KeyCode.E))
        {
            transform.Rotate(0, 0, -rotationSpeed * Time.deltaTime);
        }
    }
}

2Dキャラクターの方向転換

移動方向に応じた回転

using UnityEngine;

public class Character2DRotation : MonoBehaviour
{
    [Header("2Dキャラクター設定")]
    public float rotationSpeed = 5.0f; // 回転速度
    public bool flipSprite = false; // スプライト反転を使うか
    
    private SpriteRenderer spriteRenderer;
    private Vector2 lastPosition;
    
    void Start()
    {
        spriteRenderer = GetComponent<SpriteRenderer>();
        lastPosition = transform.position;
    }
    
    void Update()
    {
        Vector2 currentPosition = transform.position;
        Vector2 movement = currentPosition - lastPosition;
        
        if (movement.magnitude > 0.01f)
        {
            if (flipSprite)
            {
                // スプライトの左右反転
                if (movement.x > 0)
                    spriteRenderer.flipX = false;
                else if (movement.x < 0)
                    spriteRenderer.flipX = true;
            }
            else
            {
                // 移動方向に回転
                float targetAngle = Mathf.Atan2(movement.y, movement.x) * Mathf.Rad2Deg;
                Quaternion targetRotation = Quaternion.Euler(0, 0, targetAngle);
                transform.rotation = Quaternion.Slerp(
                    transform.rotation,
                    targetRotation,
                    rotationSpeed * Time.deltaTime
                );
            }
        }
        
        lastPosition = currentPosition;
    }
}

よくあるトラブルと解決方法

回転制御でよく発生する問題とその対処法を説明します。

回転速度の問題

問題1:回転が速すぎる/遅すぎる

原因と対策

// 悪い例:Time.deltaTimeを使わない
transform.Rotate(0, 90, 0); // フレームレートに依存

// 良い例:Time.deltaTimeを使用
transform.Rotate(0, 90 * Time.deltaTime, 0); // 1秒で90度

デバッグ方法

void Update()
{
    Debug.Log("Current FPS: " + (1.0f / Time.deltaTime));
    Debug.Log("Delta Time: " + Time.deltaTime);
}

ジンバルロックの問題

問題2:回転が予期しない動作をする

回避方法

// 悪い例:オイラー角の直接操作
Vector3 euler = transform.eulerAngles;
euler.x += 90;
transform.eulerAngles = euler;

// 良い例:Quaternionを使用
transform.rotation = Quaternion.Euler(90, 0, 0) * transform.rotation;

回転の滑らかさの問題

問題3:回転がガクつく

解決方法

public class SmoothRotationFix : MonoBehaviour
{
    public Transform target;
    public float rotationSpeed = 2.0f;
    
    void Update()
    {
        if (target != null)
        {
            // 目標方向を計算
            Vector3 direction = target.position - transform.position;
            direction.y = 0; // Y軸を固定
            
            if (direction != Vector3.zero)
            {
                // 滑らかな回転のためSlerpを使用
                Quaternion targetRotation = Quaternion.LookRotation(direction);
                transform.rotation = Quaternion.Slerp(
                    transform.rotation,
                    targetRotation,
                    rotationSpeed * Time.deltaTime
                );
            }
        }
    }
}

パフォーマンスの問題

問題4:回転処理が重い

最適化方法

public class OptimizedRotation : MonoBehaviour
{
    public float rotationSpeed = 90.0f;
    private float rotationTimer = 0.0f;
    private const float updateInterval = 0.016f; // 60FPS相当
    
    void Update()
    {
        rotationTimer += Time.deltaTime;
        
        // 一定間隔でのみ更新
        if (rotationTimer >= updateInterval)
        {
            transform.Rotate(0, rotationSpeed * rotationTimer, 0);
            rotationTimer = 0.0f;
        }
    }
}

座標系の混同

問題5:Local と World の回転が混同される

解決方法

// ローカル回転(オブジェクト自身の軸)
transform.Rotate(0, 90, 0, Space.Self);

// ワールド回転(世界の軸)
transform.Rotate(0, 90, 0, Space.World);

// 具体例:常にワールドのY軸中心に回転
void Update()
{
    transform.Rotate(Vector3.up * rotationSpeed * Time.deltaTime, Space.World);
}

実用的な回転システムの実装例

実際のゲームで使える回転システムの実装例を紹介します。

タワーディフェンスの砲台

敵を自動追尾する砲台

using UnityEngine;
using System.Collections.Generic;

public class TowerRotation : MonoBehaviour
{
    [Header("砲台設定")]
    public float detectionRange = 10.0f; // 探知範囲
    public float rotationSpeed = 2.0f; // 回転速度
    public Transform turretBarrel; // 砲身のTransform
    
    private Transform currentTarget;
    private List<Transform> enemies = new List<Transform>();
    
    void Update()
    {
        FindEnemies();
        SelectTarget();
        RotateToTarget();
    }
    
    void FindEnemies()
    {
        enemies.Clear();
        GameObject[] enemyObjects = GameObject.FindGameObjectsWithTag("Enemy");
        
        foreach (GameObject enemy in enemyObjects)
        {
            float distance = Vector3.Distance(transform.position, enemy.transform.position);
            if (distance <= detectionRange)
            {
                enemies.Add(enemy.transform);
            }
        }
    }
    
    void SelectTarget()
    {
        if (enemies.Count == 0)
        {
            currentTarget = null;
            return;
        }
        
        // 最も近い敵を選択
        Transform nearestEnemy = null;
        float nearestDistance = float.MaxValue;
        
        foreach (Transform enemy in enemies)
        {
            float distance = Vector3.Distance(transform.position, enemy.position);
            if (distance < nearestDistance)
            {
                nearestDistance = distance;
                nearestEnemy = enemy;
            }
        }
        
        currentTarget = nearestEnemy;
    }
    
    void RotateToTarget()
    {
        if (currentTarget == null) return;
        
        // ターゲット方向を計算
        Vector3 direction = currentTarget.position - turretBarrel.position;
        direction.y = 0; // Y軸を固定(地面と平行に回転)
        
        if (direction != Vector3.zero)
        {
            Quaternion targetRotation = Quaternion.LookRotation(direction);
            turretBarrel.rotation = Quaternion.Slerp(
                turretBarrel.rotation,
                targetRotation,
                rotationSpeed * Time.deltaTime
            );
        }
    }
    
    void OnDrawGizmosSelected()
    {
        // 探知範囲を可視化
        Gizmos.color = Color.yellow;
        Gizmos.DrawWireCircle(transform.position, detectionRange);
    }
}

惑星の公転・自転システム

天体シミュレーション

using UnityEngine;

public class PlanetaryMotion : MonoBehaviour
{
    [Header("公転設定")]
    public Transform sun; // 太陽の位置
    public float orbitDistance = 10.0f; // 公転半径
    public float orbitSpeed = 30.0f; // 公転速度(度/秒)
    public Vector3 orbitAxis = Vector3.up; // 公転軸
    
    [Header("自転設定")]
    public float rotationSpeed = 180.0f; // 自転速度(度/秒)
    public Vector3 rotationAxis = Vector3.up; // 自転軸
    
    [Header("軌道設定")]
    public float orbitEccentricity = 0.0f; // 軌道の楕円率(0=円軌道)
    public bool showOrbit = true; // 軌道表示
    
    private float currentOrbitAngle = 0.0f;
    
    void Start()
    {
        if (sun == null)
        {
            Debug.LogWarning("Sun Transform is not assigned!");
            return;
        }
        
        // 初期位置を設定
        SetInitialPosition();
    }
    
    void Update()
    {
        if (sun != null)
        {
            UpdateOrbit();
            UpdateRotation();
        }
    }
    
    void SetInitialPosition()
    {
        Vector3 initialPosition = sun.position + Vector3.forward * orbitDistance;
        transform.position = initialPosition;
    }
    
    void UpdateOrbit()
    {
        // 公転角度を更新
        currentOrbitAngle += orbitSpeed * Time.deltaTime;
        
        // 楕円軌道の計算
        float distance = orbitDistance * (1.0f - orbitEccentricity * Mathf.Cos(currentOrbitAngle * Mathf.Deg2Rad));
        
        // 新しい位置を計算
        Vector3 orbitPosition = new Vector3(
            Mathf.Cos(currentOrbitAngle * Mathf.Deg2Rad) * distance,
            0,
            Mathf.Sin(currentOrbitAngle * Mathf.Deg2Rad) * distance
        );
        
        // 太陽を中心とした位置に配置
        transform.position = sun.position + orbitPosition;
    }
    
    void UpdateRotation()
    {
        // 自転
        transform.Rotate(rotationAxis * rotationSpeed * Time.deltaTime, Space.Self);
    }
    
    void OnDrawGizmos()
    {
        if (showOrbit && sun != null)
        {
            // 軌道を可視化
            Gizmos.color = Color.cyan;
            
            // 円軌道の描画
            for (int i = 0; i < 360; i += 5)
            {
                float angle1 = i * Mathf.Deg2Rad;
                float angle2 = (i + 5) * Mathf.Deg2Rad;
                
                Vector3 point1 = sun.position + new Vector3(
                    Mathf.Cos(angle1) * orbitDistance,
                    0,
                    Mathf.Sin(angle1) * orbitDistance
                );
                
                Vector3 point2 = sun.position + new Vector3(
                    Mathf.Cos(angle2) * orbitDistance,
                    0,
                    Mathf.Sin(angle2) * orbitDistance
                );
                
                Gizmos.DrawLine(point1, point2);
            }
        }
    }
}

まとめ

Unityでのオブジェクト回転について、重要なポイントをまとめると:

基本概念の理解

  • Transform.rotation:回転の基本
  • オイラー角:人間が理解しやすい表現
  • クォータニオン:内部処理で使用される正確な表現
  • 座標軸:X、Y、Z軸の回転方向

実装方法の選択

  • インスペクター操作:手動設定、アニメーション作成
  • 基本スクリプト:transform.Rotate()、連続回転
  • 高度な制御:Quaternion.Slerp()、LookAt()
  • 物理シミュレーション:Rigidbody.AddTorque()

重要な関数とメソッド

  • transform.Rotate():基本的な回転
  • Quaternion.Slerp():滑らかな回転
  • Quaternion.LookRotation():方向を向く
  • Time.deltaTime:フレームレート非依存

2D環境での特徴

  • Z軸回転:主に使用する軸
  • スプライト反転:回転の代替手法
  • 移動方向連動:キャラクターの自然な動き

トラブル対処

  • Time.deltaTimeの使用:フレームレート問題の解決
  • Space.World vs Space.Self:座標系の理解
  • Quaternion使用:ジンバルロック回避
  • Slerp使用:滑らかな回転実現

実用的な応用例

  • 自動追尾システム:敵を向く砲台
  • 天体シミュレーション:公転・自転
  • マウス操作:直感的な回転制御
  • アニメーションカーブ:自然な動きの実現

開発効率化のコツ

  • コンポーネント化:再利用可能な設計
  • Inspector設定:デザイナーフレンドリー
  • デバッグ機能:Gizmosでの可視化
  • パフォーマンス最適化:更新頻度の調整

Unityでの回転制御は、基本を理解すれば様々な表現が可能になります。

シンプルな回転から始めて、徐々に複雑なシステムに挑戦してみてください。

コメント

タイトルとURLをコピーしました