1. 개요
유니티에서 립싱크나 또는 다양한 얼굴 표정을 구현하기 위하여 belend sahpes를 포함하고 있는 3D모델을 사용하는 것이 편하다. 다른 옵션으로는 3D모델에 Amature를 부착하여 Skin Animation을 할 수도 있다. 이번 포스팅에서는 belend sahpes를 C# 스크립트로 제어하는 예제이다.
2. 3D 모델 준비
유니티에서 사용할 3D 모델을 준비하자. 일반적으로 fbx binary format을 많이 사용한다. 3D 모델에 여러개의 belend sahpes를 만들어 준다. 인터넷에서 구한 링컨의 3D 모델은 50개의 belend sahpes를 포함하고 있다.
3. 스크립트 만들기
아래의 스크립트는 모든 belend sahpes를 순차적으로 돌아가면서 값을 변경하면서 테스트하는 프로그램이다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.IO;
public class MyLincoln : MonoBehaviour
{
public GameObject Beards; //Scene에서 마우스로 드래그 하여 설정한다.
public GameObject Bodys; //Scene에서 마우스로 드래그 하여 설정한다.
SkinnedMeshRenderer beards_skinnedMeshRenderer;
SkinnedMeshRenderer bodys_skinnedMeshRenderer;
Mesh beards_skinnedMesh;
Mesh bodys_skinnedMesh;
int blendSpeed = 2;
int blendShapeCount =0;
int dir = 1;
int current_motion = 0;
int current_weight = 0;
Dictionary<string, int> blendDict = new Dictionary<string, int>();
void Awake()
{
beards_skinnedMeshRenderer = Beards.GetComponent<SkinnedMeshRenderer>();
bodys_skinnedMeshRenderer = Bodys.GetComponent<SkinnedMeshRenderer>();
beards_skinnedMesh = Beards.GetComponent<SkinnedMeshRenderer>().sharedMesh;
bodys_skinnedMesh = Bodys.GetComponent<SkinnedMeshRenderer>().sharedMesh;
}
void Start()
{
blendShapeCount = bodys_skinnedMesh.blendShapeCount;
Debug.Log("blendShapeCount="+ blendShapeCount);
for (int i = 0; i < blendShapeCount; i++)
{
string expression = bodys_skinnedMesh.GetBlendShapeName(i);
Debug.Log(expression);
blendDict.Add(expression, i);
}
//print dictionary
foreach (KeyValuePair<string, int> pair in blendDict)
{
Debug.Log(pair);
}
}
// Update is called once per frame
void Update () {
current_weight = current_weight + blendSpeed * dir;
if (current_weight >= 100.0f)
{
dir = -1;
}
else if (current_weight <0 )
{
dir = 1;
current_motion = current_motion + 1;
current_weight = 0;
if (current_motion >= blendShapeCount) current_motion = 0;
}
// 실행 중에 Blend Shape Weight값을 바꾸어 준다.
bodys_skinnedMeshRenderer.SetBlendShapeWeight(current_motion, current_weight);
}
}
반응형