ジョー・ヒタギの止リ木 | 「ものづくり」や「ものなおし」をするブログ

色々なものを作ったり直したりするブログです。主な話題は日用品・電子機器・エアガンなど。

ジョー・ヒタギ の 止リ木

【Unity】オブジェクトの回転を別のオブジェクトと同期させるスクリプト【C#】

f:id:Jo-Bitaki:20200419172133p:plain

Unityで、あるオブジェクトAが回転した時に、別のオブジェクトBをAと同じだけ回転させるC#スクリプトをご紹介します。

このスクリプトは、3年ほど前に私がスマートフォン用VRアプリを作ろうとしたときに書きました。もともとの開発意図は、スマホの回転(=プレーヤーの頭の回転)に合わせて、自身のアバターの頭部を回転させることです。

スクリプト

言語はC#です。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class rotateQuartenion : MonoBehaviour
{
    public Transform target;
    //target : camera
    private Quaternion offsetRotation;
    // Use this for initialization
    void Start ()
    {
        offsetRotation = Quaternion.Inverse (target.transform.rotation) * transform.rotation;
    }
    
    // Update is called once per frame
    void Update ()
    {
        transform.rotation = target.transform.rotation * offsetRotation;
    }
}

このスクリプトはUnity 5.6.3p2での動作を確認しています。おそらく最新版でも動くとは思いますが、現在の私の環境ではUnityを起動できないため未確認です。

使い方

  1. 動かしたいオブジェクト(例:キャラクターの頭部)にスクリプトをアタッチ
  2. 回転を同期させたいオブジェクト(例:Main Camera)をターゲットに設定

スクリプトの解説

動作自体は次のように極めてシンプルです。

  1. 起動時、アタッチされたオブジェクト(A)とターゲットとなるオブジェクト(B)の回転姿勢の差を計算
  2. 毎フレームごとに、AとBの回転姿勢の差が起動時と同じになるようにBの回転をオーバーライド

回転角度の取得・操作には一般的(?)なオイラー角ではなく四元数(Quaternion)を使っています。

オイラー角では、物体の姿勢を互いに直交する3軸の回転(ロール・ピッチ・ヨー)の組み合わせで表現します(下図参照)。

f:id:Jo-Bitaki:20200419172152p:plain:h350

引用元:Wikipedia( https://commons.wikimedia.org/wiki/File:Yaw_Axis_Corrected.svg

この方式は直感的で分かりやすいのですが、

  • 条件によっては姿勢を一意に特定できない
  • 2つの物体の姿勢の差を計算しにくい

というデメリットがありそうだったので使いませんでした。

一方の四元数は物体の姿勢を4つの変数の行列で表現します。
複素数を拡張したものらしいのですが、私は本質的なことについて何一つ理解していません。

おわりに

本スクリプトは私が3年ほど前に書いたものです。現在は(もしかしたら当時も)より洗練されたやり方があるのかもしれません。
PCの整理中にスクリプトを見つけたのと、「コロナウイルスによる自粛中にUnityを勉強し始める方がいるかもしれない」と思ったので紹介させてもらいました。

もしもスクリプトを使っていただけましたら、コメントや お問い合わせフォーム でお知らせくださると非常にうれしいです。

おまけ:頭の描画に関する注意点

蛇足ですが、VRゲームでの頭の描画に関する注意点を1つ。

VRゲームでアバターを使用する場合、プレーヤーの視界となるカメラにはアバターの頭部(あるいは首も)を描画しないことをおすすめします。さもないと、カメラがモデルにめり込んでグロ画像が映ることに…

「じゃあ、頭を動かすスクリプトなんて必要ないだろう」と思われるかもしれませんが、ゲーム内に鏡*1や他のプレーヤーが存在する場合、それらのカメラには頭部をきちんと描画する必要があるのです。

関連記事

【Unity】スマホだけで6DoFのVRを実現したサンプルプロジェクトの紹介

MMD ☓ Songleの読み込みが終わらない・再生ボタンが表示されない・落ちるときの対処法

*1:VR空間で鏡を実装するには視差の問題をクリアしなければならず、複雑な計算が必要となるようです。私は挫折しました。