「Unity/VRM」の版間の差分
提供: 初心者エンジニアの簡易メモ
(→モデルを動的に読み込む場合) |
(→表情変更) |
||
(同じ利用者による、間の4版が非表示) | |||
行32: | 行32: | ||
Debug.Log(path); | Debug.Log(path); | ||
RuntimeGltfInstance instance = await VrmUtility.LoadAsync(path, new RuntimeOnlyAwaitCaller()); | RuntimeGltfInstance instance = await VrmUtility.LoadAsync(path, new RuntimeOnlyAwaitCaller()); | ||
− | |||
instance.ShowMeshes(); | instance.ShowMeshes(); | ||
} | } | ||
行38: | 行37: | ||
</pre> | </pre> | ||
参考:https://zenn.dev/nishi/articles/c44fc709a7d575 | 参考:https://zenn.dev/nishi/articles/c44fc709a7d575 | ||
+ | |||
+ | ===表情変更=== | ||
+ | 笑顔に変更 | ||
+ | <pre> | ||
+ | using UnityEngine; | ||
+ | using UniGLTF; | ||
+ | using VRM; | ||
+ | using VRMShaders; | ||
+ | VRMBlendShapeProxy proxy = vrmObj.GetComponent<VRMBlendShapeProxy>(); | ||
+ | proxy.SetValues(new Dictionary<BlendShapeKey, float> | ||
+ | { | ||
+ | {BlendShapeKey.CreateFromPreset(BlendShapePreset.Joy), 1.0f}, | ||
+ | }); | ||
+ | </pre> | ||
+ | |||
+ | 参考:https://vrm-c.github.io/UniVRM/ja/api/0_58_blendshape.html | ||
+ | |||
+ | * SetValuesは、推奨 | ||
+ | * ImmediatelySetValueは、非推奨っぽい。 | ||
+ | |||
+ | ===表情を徐々に変更=== | ||
+ | <pre> | ||
+ | using UnityEngine; | ||
+ | using UniGLTF; | ||
+ | using VRM; | ||
+ | using VRMShaders; | ||
+ | public class SampleScene : MonoBehaviour | ||
+ | { | ||
+ | [SerializeField] GameObject vrmObj; | ||
+ | void Start() | ||
+ | { | ||
+ | VrmStart(); | ||
+ | } | ||
+ | void VrmStart() | ||
+ | { | ||
+ | float sec = 0; | ||
+ | StartCoroutine(DelayVRMBlend(sec, BlendShapePreset.Angry)); | ||
+ | sec += 0.5f; | ||
+ | StartCoroutine(DelayVRMBlend(sec, BlendShapePreset.A)); | ||
+ | sec += 0.5f; | ||
+ | StartCoroutine(DelayVRMBlend(sec, BlendShapePreset.I)); | ||
+ | sec += 0.5f; | ||
+ | StartCoroutine(DelayVRMBlend(sec, BlendShapePreset.U)); | ||
+ | sec += 0.5f; | ||
+ | StartCoroutine(DelayVRMBlend(sec, BlendShapePreset.E)); | ||
+ | sec += 0.5f; | ||
+ | StartCoroutine(DelayVRMBlend(sec, BlendShapePreset.O)); | ||
+ | sec += 1f; | ||
+ | StartCoroutine(DelayVRMBlend(sec, BlendShapePreset.Fun)); | ||
+ | sec += 1f; | ||
+ | StartCoroutine(DelayVRMBlend(sec, BlendShapePreset.Joy)); | ||
+ | } | ||
+ | VRMBlendShapeProxy proxy; | ||
+ | IEnumerator DelayVRMBlend(float delay, BlendShapePreset preset) | ||
+ | { | ||
+ | yield return new WaitForSeconds(delay); | ||
+ | if (proxy == null) | ||
+ | { | ||
+ | proxy = vrmObj.GetComponent<VRMBlendShapeProxy>(); | ||
+ | } | ||
+ | ResetBlendShape(); | ||
+ | proxy.SetValues(new Dictionary<BlendShapeKey, float> | ||
+ | { | ||
+ | {BlendShapeKey.CreateFromPreset(preset), 1.0f}, | ||
+ | }); | ||
+ | } | ||
+ | // 初期化 | ||
+ | void ResetBlendShape() | ||
+ | { | ||
+ | if (proxy != null) | ||
+ | { | ||
+ | proxy.SetValues(new Dictionary<BlendShapeKey, float> | ||
+ | { | ||
+ | { BlendShapeKey.CreateFromPreset(BlendShapePreset.Neutral), 0f}, | ||
+ | { BlendShapeKey.CreateFromPreset(BlendShapePreset.A), 0f}, | ||
+ | { BlendShapeKey.CreateFromPreset(BlendShapePreset.I), 0f}, | ||
+ | { BlendShapeKey.CreateFromPreset(BlendShapePreset.U), 0f}, | ||
+ | { BlendShapeKey.CreateFromPreset(BlendShapePreset.E), 0f}, | ||
+ | { BlendShapeKey.CreateFromPreset(BlendShapePreset.O), 0f}, | ||
+ | { BlendShapeKey.CreateFromPreset(BlendShapePreset.Blink), 0f}, | ||
+ | { BlendShapeKey.CreateFromPreset(BlendShapePreset.Joy), 0f}, | ||
+ | { BlendShapeKey.CreateFromPreset(BlendShapePreset.Angry), 0f}, | ||
+ | { BlendShapeKey.CreateFromPreset(BlendShapePreset.Sorrow), 0f}, | ||
+ | { BlendShapeKey.CreateFromPreset(BlendShapePreset.Fun), 0f}, | ||
+ | { BlendShapeKey.CreateFromPreset(BlendShapePreset.LookUp), 0f}, | ||
+ | { BlendShapeKey.CreateFromPreset(BlendShapePreset.LookDown), 0f}, | ||
+ | { BlendShapeKey.CreateFromPreset(BlendShapePreset.LookLeft), 0f}, | ||
+ | { BlendShapeKey.CreateFromPreset(BlendShapePreset.LookRight), 0f}, | ||
+ | { BlendShapeKey.CreateFromPreset(BlendShapePreset.Blink_L), 0f}, | ||
+ | { BlendShapeKey.CreateFromPreset(BlendShapePreset.Blink_R), 0f}, | ||
+ | }); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </pre> |
2022年12月18日 (日) 06:03時点における最新版
UnityでVRMを動かす方法
参考:https://konichallengelog.com/unity_vrm_lipsync/
人形素材をDLとインストール
- https://3d.nicovideo.jp/works/td32797 からDL
- DLしたdirを、UnityのAssets以下にドラッグ
- VRM内の青色アイコンのPrefabを、ヒエラルキーにドラッグして、表示されればOK
UniVRMのインストール
Package/manifest.jsonのdependencies以下に、com.vrmc〜の4行追加
"dependencies": { "com.vrmc.vrmshaders": "https://github.com/vrm-c/UniVRM.git?path=/Assets/VRMShaders#v0.107.0", "com.vrmc.gltf": "https://github.com/vrm-c/UniVRM.git?path=/Assets/UniGLTF#v0.107.0", "com.vrmc.univrm": "https://github.com/vrm-c/UniVRM.git?path=/Assets/VRM#v0.107.0", "com.vrmc.vrm": "https://github.com/vrm-c/UniVRM.git?path=/Assets/VRM10#v0.107.0",
Unityプロジェクトを開いて、Packagesの下に、VRMが、あれば成功。
モデルを動的に読み込む場合
pathは適当。読み込み時間は7秒ぐらいかかる。
using UnityEngine; using UniGLTF; using VRM; using VRMShaders; public class SampleScene : MonoBehaviour { async void Start() { string path = Application.streamingAssetsPath + "/../Alicia_VRM/Alicia/VRM/AliciaSolid.vrm"; Debug.Log(path); RuntimeGltfInstance instance = await VrmUtility.LoadAsync(path, new RuntimeOnlyAwaitCaller()); instance.ShowMeshes(); } }
参考:https://zenn.dev/nishi/articles/c44fc709a7d575
表情変更
笑顔に変更
using UnityEngine; using UniGLTF; using VRM; using VRMShaders; VRMBlendShapeProxy proxy = vrmObj.GetComponent<VRMBlendShapeProxy>(); proxy.SetValues(new Dictionary<BlendShapeKey, float> { {BlendShapeKey.CreateFromPreset(BlendShapePreset.Joy), 1.0f}, });
参考:https://vrm-c.github.io/UniVRM/ja/api/0_58_blendshape.html
- SetValuesは、推奨
- ImmediatelySetValueは、非推奨っぽい。
表情を徐々に変更
using UnityEngine; using UniGLTF; using VRM; using VRMShaders; public class SampleScene : MonoBehaviour { [SerializeField] GameObject vrmObj; void Start() { VrmStart(); } void VrmStart() { float sec = 0; StartCoroutine(DelayVRMBlend(sec, BlendShapePreset.Angry)); sec += 0.5f; StartCoroutine(DelayVRMBlend(sec, BlendShapePreset.A)); sec += 0.5f; StartCoroutine(DelayVRMBlend(sec, BlendShapePreset.I)); sec += 0.5f; StartCoroutine(DelayVRMBlend(sec, BlendShapePreset.U)); sec += 0.5f; StartCoroutine(DelayVRMBlend(sec, BlendShapePreset.E)); sec += 0.5f; StartCoroutine(DelayVRMBlend(sec, BlendShapePreset.O)); sec += 1f; StartCoroutine(DelayVRMBlend(sec, BlendShapePreset.Fun)); sec += 1f; StartCoroutine(DelayVRMBlend(sec, BlendShapePreset.Joy)); } VRMBlendShapeProxy proxy; IEnumerator DelayVRMBlend(float delay, BlendShapePreset preset) { yield return new WaitForSeconds(delay); if (proxy == null) { proxy = vrmObj.GetComponent<VRMBlendShapeProxy>(); } ResetBlendShape(); proxy.SetValues(new Dictionary<BlendShapeKey, float> { {BlendShapeKey.CreateFromPreset(preset), 1.0f}, }); } // 初期化 void ResetBlendShape() { if (proxy != null) { proxy.SetValues(new Dictionary<BlendShapeKey, float> { { BlendShapeKey.CreateFromPreset(BlendShapePreset.Neutral), 0f}, { BlendShapeKey.CreateFromPreset(BlendShapePreset.A), 0f}, { BlendShapeKey.CreateFromPreset(BlendShapePreset.I), 0f}, { BlendShapeKey.CreateFromPreset(BlendShapePreset.U), 0f}, { BlendShapeKey.CreateFromPreset(BlendShapePreset.E), 0f}, { BlendShapeKey.CreateFromPreset(BlendShapePreset.O), 0f}, { BlendShapeKey.CreateFromPreset(BlendShapePreset.Blink), 0f}, { BlendShapeKey.CreateFromPreset(BlendShapePreset.Joy), 0f}, { BlendShapeKey.CreateFromPreset(BlendShapePreset.Angry), 0f}, { BlendShapeKey.CreateFromPreset(BlendShapePreset.Sorrow), 0f}, { BlendShapeKey.CreateFromPreset(BlendShapePreset.Fun), 0f}, { BlendShapeKey.CreateFromPreset(BlendShapePreset.LookUp), 0f}, { BlendShapeKey.CreateFromPreset(BlendShapePreset.LookDown), 0f}, { BlendShapeKey.CreateFromPreset(BlendShapePreset.LookLeft), 0f}, { BlendShapeKey.CreateFromPreset(BlendShapePreset.LookRight), 0f}, { BlendShapeKey.CreateFromPreset(BlendShapePreset.Blink_L), 0f}, { BlendShapeKey.CreateFromPreset(BlendShapePreset.Blink_R), 0f}, }); } } }