Onoty3D

Unityに関するメモとか

プロ生ちゃんの視線を操作する(Transform.LookAt)

f:id:onoty3d:20150331105603g:plain

プロ生ちゃんの視線に関して。
カメラ目線にする方法としてはBlendShapeの「コッチミンナ」があり、これを利用すると常にこっちを向いているような状態にすることができます。
これはだまし絵おもちゃと同じ原理で、瞳をやや奥(頭の中央方向)に移動させることで、常に白目の余白をカメラと反対方向に発生させ、結果瞳がこちらを向いているかのように錯覚させています。
カメラ目線であればこれでも十分ですが、任意の方向に視線をやりたいときには使えません。

プロ生ちゃんの目は、rotationの値を変更することでグリグリ回すことができます(※)。
これを利用して、対象を目で追いかけるスクリプトを書いてみます。

※Rigの設定で目の割り当てをしていると回せないようなので、rotationで直接弄りたい場合は、設定を外しましょう(デフォルトでは設定されていません)。
f:id:onoty3d:20150331190614j:plain

スクリプトを書くといっても、Transformに対象の方向を向くLookAtというメソッドが用意されているので、それを呼ぶだけです。
Unity - スクリプティング API: Transform.LookAt
ただ、LookAtはZ軸を対象に向けて回転させるメソッドなので、多少補正が必要です。
またメソッドの第2引数を指定しない場合、Y軸方向を上に回転してしまうので、そこも調整します。

まず上にすべき軸の方向の決定。
これは瞳の回転を(0, 0, 0)にして確認。こうするとプロ生ちゃんの瞳はX軸の逆方向が上になっているのが分かります。
f:id:onoty3d:20150331105652p:plain
よってLookAtの第2引数には、X軸方向(Vector3.right)にマイナスを掛けたものを指定します。

次にLookAt後の補正。
LookAt後のlocalRotationの値で、無回転状態(0, 0, 0)から幾ら回転したかが取得できます。
プロ生ちゃんの目は初期状態で回転しているので、このrotationに元々回転していた分を加えます(クォータニオンを掛けることで回転の加算になるらしい…)。

以上で補正は完了です。

ソース

using UnityEngine;

namespace PronamaChan
{
    public class LookTarget : MonoBehaviour
    {
        public Transform EyeL;
        public Transform EyeR;
        public Transform Target;

        private Quaternion _defaultRotationL;
        private Quaternion _defaultRotationR;

        // Use this for initialization
        void Start()
        {
            this._defaultRotationL = this.EyeL.localRotation;
            this._defaultRotationR = this.EyeR.localRotation;
        }

        // Update is called once per frame
        void Update()
        {
            if (this.Target == null) return;

            this.EyeL.LookAt(this.Target, -Vector3.right);
            this.EyeL.localRotation *= this._defaultRotationL;

            this.EyeR.LookAt(this.Target, -Vector3.right);
            this.EyeR.localRotation *= this._defaultRotationR;
        }
    }
}

スクリプトをプロ生ちゃんモデルに適用したら、EyeL,EyeRにプロ生ちゃんのeye_L,eye_R、Targetに目で追いかけたい対象を指定してください。

なお、このままだと常に瞳が対象を追いかけるので、一定範囲を超えたら白目になってしまいます。
回転角に制限をつけたりして抑制する必要があるかと思います。