本日はReallusion&Unity枠です。
〇環境
・Windows11PC
・Unity2022.3.26f1
〇瞳孔
人間は様々な条件で瞳孔の大きさが変わります。
瞳孔は交感神経、副交感神経や環境の明るさ、見ているものの距離によって変わります。これは生理的な反応であり、意識して瞳孔の大きさを変えるものではありません。
また、近くのものを見るときと遠くのものを見る時では水晶体の厚みが変わり、屈折力が変わります。
これらの変化をCharactorCreator製のキャラクターで実装します。
前提としてCCToolsを用いてUnityにインポートしてMaterialの設定を行っていることから始めます。
〇瞳孔の変化
Reallusionの提供するシェーダーでは瞳用のシェーダーが用意されています。URPの場合はRL_Amplify_CorneaShaderParallax_URPシェーダーです。

このシェーダーでは、瞳の大きさや色の他にIOR(屈折率)やPupilScale(瞳孔)の設定ができます。


この値をC#側で調整可能にしたものが以下になります。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace SOADA3DART.Pharmacetical
{
public class EnvManager : MonoBehaviour
{
public bool useDefaultSettings = true; // デフォルト設定を使用するかどうか
[Header("Environment Settings")] [SerializeField]
private int DayTime = 12; // 環境が昼か夜か
public DayTimeS DayTimeSetting = DayTimeS.noon; // 環境の昼夜設定
public enum DayTimeS
{
earlyMorning, // 早朝
morning, // 朝
noon, // 昼
evening, // 夕方
night, // 夜
middnight // 真夜中
}
// Start is called before the first frame update
void Start()
{
if (!useDefaultSettings)
{
//現在の時刻を取得
System.DateTime currentTime = System.DateTime.Now;
DayTime = currentTime.Hour; // 現在の時間を取得
// 環境の昼夜を設定
switch (DayTime)
{
case <4 :
DayTimeSetting = DayTimeS.middnight; // 0時から3時は真夜中
break;
case <7:
DayTimeSetting = DayTimeS.earlyMorning;
break;
case <10:
DayTimeSetting = DayTimeS.morning; // 4時から6時は早朝
break;
case <15:
DayTimeSetting = DayTimeS.noon; // 7時から14時は昼
break;
case <18:
DayTimeSetting = DayTimeS.evening; // 15時から17時は夕方
break;
case <21:
DayTimeSetting = DayTimeS.night; // 18時から20時は夜
break;
case <24:
DayTimeSetting = DayTimeS.middnight; // 21時から23時は真夜中
break;
}
}
}
}
}
GameObject _lookAtTarget; // 目の注視ターゲット
[Header("IrisSettings"),SerializeField]
Material[] _irisMaterials; // アイリスのマテリアル
[SerializeField] float _pupilScale = 0.5f;
public enum SleepState
{
less,
Sleepy,
normal
}
public void SetIrisSettingsWithEnv()
{
switch (_envManager.DayTimeSetting)
{
case EnvManager.DayTimeS.earlyMorning:
StartCoroutine(changeIrisSize(0.7f, 1f));
break;
case EnvManager.DayTimeS.morning:
StartCoroutine(changeIrisSize(0.65f, 1f));
break;
case EnvManager.DayTimeS.noon:
StartCoroutine(changeIrisSize(0.55f, 1f));
break;
case EnvManager.DayTimeS.evening:
StartCoroutine(changeIrisSize(0.65f, 1f));
break;
case EnvManager.DayTimeS.night:
StartCoroutine(changeIrisSize(0.8f, 1f));
break;
case EnvManager.DayTimeS.middnight:
StartCoroutine(changeIrisSize(0.9f,1f));
break;
}
}
//なだらかに瞳孔の大きさを変更する
IEnumerator changeIrisSize(float targetSize, float duration)
{
_pupilScale = targetSize;
float startSizeR = _irisMaterials[0].GetFloat("_PupilScale");
float startSizeL = _irisMaterials[1].GetFloat("_PupilScale");
float elapsedTime = 0f;
while (elapsedTime < duration)
{
elapsedTime += Time.deltaTime;
float t = Mathf.Clamp01(elapsedTime / duration);
float newSizeR = Mathf.Lerp(startSizeR, targetSize, t);
float newSizeL = Mathf.Lerp(startSizeL, targetSize, t);
_irisMaterials[0].SetFloat("_PupilScale", newSizeR);
_irisMaterials[1].SetFloat("_PupilScale", newSizeL);
yield return null;
}
}
public void SetIrisSizewithCharactorState()
{
SetIrisSettingsWithEnv();
switch (_sleepState)
{
case SleepState.less:
_pupilScale *= 0.8f;
break;
case SleepState.Sleepy:
_pupilScale *= 0.9f; // 眠い
break;
case SleepState.normal:
break;
}
switch (_spO2)
{
case SpO2.Normal:
_pupilScale *= 1f; // 正常
break;
case SpO2.Hypoxemia:
_pupilScale *= 0.8f; // 低酸素血症
break;
}
_irisMaterials[0].SetFloat("_PupilScale", _pupilScale);
_irisMaterials[1].SetFloat("_PupilScale", _pupilScale);
}
public void SetIrisWithDistance()
{
//_lookAtTargetとの値に応じて瞳孔の大きさとIOCを変える。
float distance = Vector3.Distance(_lookAtTarget.transform.position, _EyeR.position)/5f;
distance = 1 + (0.5f - Mathf.Clamp01(distance));
_pupilScale *= 1 +( 0.5f - Mathf.Clamp01(distance));
_irisMaterials[0].SetFloat("_PupilScale" ,_pupilScale);
_irisMaterials[0].SetFloat("_IOR" ,1.4f - distance*3);
_irisMaterials[1].SetFloat("_PupilScale" ,_pupilScale);
_irisMaterials[1].SetFloat("_IOR" , 1.4f - distance*3);
}
コア部分はMaterial.SetFloat("_PupilScale" ,_pupilScale)とMaterial.SetFloat("_IOR" , 1.4f - distance*3)です。
これは瞳のシェーダーのパラメータに値を渡しています。
どのような値を与えるかという点で、ここでは環境や体調によって細かく基本的なパラメータを与えて、最終的にはGameObject _lookAtTargetの値で注視しているオブジェクトとの距離で変化させています。
これ次実際に動かしたものが以下になります。

以上で瞳孔のコントロールができるようになりました。本日は以上です。