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

Onoty3D

Unityに関するメモとか

プロ生ちゃんの表情を変化させる

以下に説明がありますが、プロ生ちゃんの表情はSkinnedMeshRendererのBlendShapesの各パラメータで設定できます。

暮井 慧(プロ生ちゃん)3D モデル Unity パッケージ公開!
http://pronama.azurewebsites.net/2014/08/20/kurei-kei-3d-model-unity-package/

どんな数値でも設定できますが、0~100の範囲がMIN-MAXになっており、0以下は0、100以上は100と変わりありません。

インスペクタ上で値を設定してもよいですが、実行中に画面上でもパラメータを変更できるようなスクリプトを書いてみました。

using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace PronamaChan
{
    public class FaceUpdate : MonoBehaviour
    {
        public SkinnedMeshRenderer SkinnedMeshRenderer;

        //各スライダーの現在値を保持するリスト
        private List<float> _sliderValues;

        //BlendShape名の表示スタイル
        private GUIStyle _labelTitleStyle;

        //スライダー値の表示スタイル
        private GUIStyle _labelValueStyle;

        private void Start()
        {
            //SkinnedMeshRendererの取得
            if (this.SkinnedMeshRenderer == null) this.SkinnedMeshRenderer = this.GetComponentInChildren<SkinnedMeshRenderer>();

            this._sliderValues = Enumerable.Repeat<float>(0f, this.SkinnedMeshRenderer.sharedMesh.blendShapeCount).ToList();

            this._labelTitleStyle = new GUIStyle { fixedWidth = 80f, alignment = TextAnchor.MiddleRight, normal = new GUIStyleState { textColor = Color.white } };
            this._labelValueStyle = new GUIStyle { fixedWidth = 20f, alignment = TextAnchor.MiddleRight, normal = new GUIStyleState { textColor = Color.white } };
        }

        private void OnGUI()
        {
            GUILayout.Box("", GUILayout.Width(220), GUILayout.Height(15 * (this.SkinnedMeshRenderer.sharedMesh.blendShapeCount + 1)));
            Rect screenRect = new Rect(10, 10, 190, 15 * (this.SkinnedMeshRenderer.sharedMesh.blendShapeCount + 1));
            GUILayout.BeginArea(screenRect);
            for (int index = 0; index < this.SkinnedMeshRenderer.sharedMesh.blendShapeCount; index++)
            {
                GUILayout.BeginHorizontal();

                //BlendShape名
                GUILayout.Label(this.SkinnedMeshRenderer.sharedMesh.GetBlendShapeName(index), this._labelTitleStyle);

                //スライダー
                this._sliderValues[index] = GUILayout.HorizontalSlider(this._sliderValues[index], 0f, 100f);

                //スライダーの値
                GUILayout.Label(this._sliderValues[index].ToString("#0"), this._labelValueStyle);

                GUILayout.EndHorizontal();

                //スライダーの値をBlendShapeに反映
                this.SkinnedMeshRenderer.SetBlendShapeWeight(index, this._sliderValues[index]);
            }
            GUILayout.EndArea();
        }

        private void Update()
        {
        }
    }
}

f:id:onoty3d:20150223205456j:plain
SkinnedMeshRendererが未指定の場合、
Startメソッド内部で
this.GetComponentInChildren();
でSkinnedMeshRendererを取得していますが、プロ生ちゃんモデルの中にSkinnedMeshRendererを持つ別のオブジェクトを内包させた場合、そちらが取得される可能性もあります。
そのような使い方をする場合は、プロ生ちゃん本体のSkinnedMeshRendererを事前に指定してください。

余談:ぐるぐる回す部分はforeachを使いたいんだけど、Unityでforeachはあんまりいい噂聞かないので、とりあえずforで回している。