Last active
September 24, 2016 12:32
-
-
Save dskjal/17034ad3b97bc6596248881f02caaafe to your computer and use it in GitHub Desktop.
ユニティちゃんの瞬きを滑らかにする
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
//AutoBlink.cs | |
//オート目パチスクリプト | |
//2014/06/23 N.Kobayashi | |
//2016/09/19 dakjal | |
// ライセンスについてはユニティちゃんライセンス(http://unity-chan.com/contents/license_jp/)を参照. | |
// | |
using UnityEngine; | |
using System.Collections; | |
namespace UnityChan | |
{ | |
public class AutoBlink : MonoBehaviour | |
{ | |
public bool isActive = true; //オート目パチ有効 | |
public SkinnedMeshRenderer ref_SMR_EYE_DEF; //EYE_DEFへの参照 | |
public SkinnedMeshRenderer ref_SMR_EL_DEF; //EL_DEFへの参照 | |
public float ratio_Close = 85.0f; //閉じ目ブレンドシェイプ比率 | |
public float ratio_HalfClose = 20.0f; //半閉じ目ブレンドシェイプ比率 | |
[HideInInspector] | |
public float ratio_Open = 0.0f; | |
public float timeBlink = 0.4f; //目パチの時間 | |
public float threshold = 0.3f; // ランダム判定の閾値 | |
public float interval = 3.0f; // ランダム判定のインターバル | |
class EyelidAnimator { | |
private float timeBlinkSec; | |
private float timeRemaining = 0f; | |
private SkinnedMeshRenderer ref_SMR_EYE_DEF;//EYE_DEFへの参照 | |
private SkinnedMeshRenderer ref_SMR_EL_DEF; //EL_DEFへの参照 | |
enum Status | |
{ | |
Open = 0, | |
HalfClose, | |
Close, | |
HalfOpen, | |
NotAnimating, | |
STATUS_LENGTH | |
} | |
private Status eyeStatus; //現在の目パチステータス | |
struct StateTransition { | |
public Status NextState; | |
public float StartWeight; | |
public float EndWeight; | |
} | |
StateTransition[] stateTable = new StateTransition[(int)Status.STATUS_LENGTH]; | |
public EyelidAnimator(SkinnedMeshRenderer eyeDef, SkinnedMeshRenderer elDef) { | |
ref_SMR_EYE_DEF = eyeDef; | |
ref_SMR_EL_DEF = elDef; | |
stateTable[0].NextState = Status.HalfClose; | |
stateTable[1].NextState = Status.Close; | |
stateTable[2].NextState = Status.HalfOpen; | |
stateTable[3].NextState = Status.NotAnimating; | |
} | |
public void Start(float timeBlinkSec, float ratioClose, float ratioHalfClose, float ratioOpen) { | |
this.timeBlinkSec = timeBlinkSec / 4f; | |
timeRemaining = this.timeBlinkSec; | |
eyeStatus = Status.Open; | |
stateTable[3].EndWeight = stateTable[0].StartWeight = ratioOpen; | |
stateTable[0].EndWeight = stateTable[1].StartWeight = ratioHalfClose; | |
stateTable[1].EndWeight = stateTable[2].StartWeight = ratioClose; | |
stateTable[2].EndWeight = stateTable[3].StartWeight = ratioHalfClose; | |
} | |
private void setRatio(float ratio) { | |
ref_SMR_EYE_DEF.SetBlendShapeWeight(6, ratio); | |
ref_SMR_EL_DEF.SetBlendShapeWeight(6, ratio); | |
} | |
// Must call every frame | |
public void Update() { | |
if (!IsAnimating()) { | |
return; | |
} | |
timeRemaining -= Time.deltaTime; | |
// 残り時間が少なくなるにつれて 1 に近づく | |
var animWeight = 1f - Mathf.Clamp(timeRemaining/this.timeBlinkSec, 0, 1); | |
var stateData = stateTable[(int)eyeStatus]; | |
if (timeRemaining < 0f) { | |
eyeStatus = stateData.NextState; | |
timeRemaining += timeBlinkSec; | |
} | |
var ratio = Mathf.Lerp(stateData.StartWeight, stateData.EndWeight, animWeight); | |
setRatio(ratio); | |
} | |
public bool IsAnimating() { | |
return eyeStatus != Status.NotAnimating; | |
} | |
} | |
private EyelidAnimator eyelidAnimator; | |
void Awake () | |
{ | |
//ref_SMR_EYE_DEF = GameObject.Find("EYE_DEF").GetComponent<SkinnedMeshRenderer>(); | |
//ref_SMR_EL_DEF = GameObject.Find("EL_DEF").GetComponent<SkinnedMeshRenderer>(); | |
eyelidAnimator = new EyelidAnimator(ref_SMR_EYE_DEF, ref_SMR_EL_DEF); | |
} | |
void Start () | |
{ | |
// ランダム判定用関数をスタートする | |
StartCoroutine ("RandomChange"); | |
} | |
void Update () | |
{ | |
if (isActive) { | |
eyelidAnimator.Update(); | |
} | |
} | |
// ランダム判定用関数 | |
IEnumerator RandomChange () | |
{ | |
// 無限ループ開始 | |
while (true) { | |
//ランダム判定用シード発生 | |
float _seed = Random.Range (0.0f, 1.0f); | |
if (!eyelidAnimator.IsAnimating()) { | |
if (_seed > threshold) { | |
eyelidAnimator.Start(timeBlink, ratio_Close, ratio_HalfClose, ratio_Open); | |
} | |
} | |
// 次の判定までインターバルを置く | |
yield return new WaitForSeconds (interval); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment