読者です 読者をやめる 読者になる 読者になる

Onoty3D

Unityに関するメモとか

プロ生ちゃんの瞳を更に操作する

f:id:onoty3d:20150331194409p:plain
さて、前回・前々回と視線の変更というか瞳の回転ネタをやりましたが、個人的にIKを使わないほうがrotationを細かく設定出来たりして好きです。
rotationを直接操作する方法の方で、ターゲットを目で追うのではなく回転角度を直接いじるタイプのスクリプトも書いてみました。
ついでに更に色々出来るようにしています。

できる事は

瞳の回転
f:id:onoty3d:20150331194320p:plain

瞳の大きさ変更
f:id:onoty3d:20150331194344p:plain

ハイライトのON/OFF
f:id:onoty3d:20150331194425p:plain

です。
目は口ほどに物を言う…といいますが、これだけでもずいぶん表情の幅が増えます。

ソース

using UnityEngine;

namespace PronamaChan
{
    public class EyeSettings : MonoBehaviour
    {
        public Transform EyeL;
        public Transform EyeR;
        public SkinnedMeshRenderer SkinnedMesh;
        public Material TransparentMaterial; //ハイライトを消すときの代替用マテリアル

        [HeaderAttribute("目の回転")]
        public bool SyncLRRotation = true; //左右の回転を同期するか(左の回転に同期します)

        [Range(-22f, 30f)]
        public float EyeLRotationY = 0f;

        [Range(-22f, 30f)]
        public float EyeRRotationY = 0f;

        [Range(-35f, 35f)]
        public float EyeLRotationZ = 0f;

        [Range(-35f, 35f)]
        public float EyeRRotationZ = 0f;

        [HeaderAttribute("目の大きさ")]
        public bool SyncLRSize = true; //左右の大きさを同期するか(左のサイズに同期します)

        [Range(0f, 1.5f)]
        public float EyeLScaleY = 1f;

        [Range(0f, 1.5f)]
        public float EyeRScaleY = 1f;

        [Range(0f, 1.5f)]
        public float EyeLScaleZ = 1f;

        [Range(0f, 1.5f)]
        public float EyeRScaleZ = 1f;

        [HeaderAttribute("ハイライト")]
        public bool ShowHighLight = true;

        private Vector3 _defaultRotationL;
        private Vector3 _defaultRotationR;
        private Material _highLightMaterial;
        private bool _isStarted;

        // Use this for initialization
        private void Start()
        {
            this._isStarted = true;

            //目の回転の初期値取得
            this._defaultRotationL = this.EyeL.localRotation.eulerAngles;
            this._defaultRotationR = this.EyeR.localRotation.eulerAngles;

            this._highLightMaterial = this.SkinnedMesh.materials[7];
        }

        // Update is called once per frame
        private void Update()
        {
        }

        public void OnValidate()
        {
            if (Application.isPlaying && this._isStarted)
            {
                //目の回転
                if (this.SyncLRRotation)
                {
                    this.EyeRRotationY = this.EyeLRotationY;
                    this.EyeRRotationZ = this.EyeLRotationZ;
                }
                var rotation = this._defaultRotationL;
                rotation.y += this.EyeLRotationY;
                rotation.z += this.EyeLRotationZ;
                this.EyeL.localRotation = Quaternion.Euler(rotation);

                rotation = this._defaultRotationR;
                rotation.y += this.EyeRRotationY;
                rotation.z += this.EyeRRotationZ;
                this.EyeR.localRotation = Quaternion.Euler(rotation);

                //目の大きさ
                if (this.SyncLRSize)
                {
                    this.EyeRScaleY = this.EyeLScaleY;
                    this.EyeRScaleZ = this.EyeLScaleZ;
                }

                this.EyeL.localScale = new Vector3(1f, this.EyeLScaleY, this.EyeLScaleZ);
                this.EyeR.localScale = new Vector3(1f, this.EyeRScaleY, this.EyeRScaleZ);

                //ハイライト
                var materials = this.SkinnedMesh.materials;
                materials[7] = this.ShowHighLight ? this._highLightMaterial : this.TransparentMaterial;
                this.SkinnedMesh.materials = materials;
            }
        }
    }
}

インスペクタでの表示はこんな感じ。
f:id:onoty3d:20150331194535p:plain

ハイライトのON/OFFは、実際にはハイライトのMaterialと透明なMaterialを交互に切り替えています。
別途適当に透明なMaterialを作って設定してください。
f:id:onoty3d:20150331194825p:plain
EyeL,EyeRにはプロ生ちゃんの左右の目、SkinnedMeshにはプロ生ちゃんのSkinnedMeshRendererをセットしてください。

実行中のみ操作可能です。
今回はエディタ上でいじって遊ぶように作っただけなので、OnValidateで処理を行っています。
コンテンツとしてきちんと作る場合はUpdateで処理したり、任意のタイミングで処理を呼び出すように変更する必要があるかと思います。