Merge pull request #2436 from ousttrue/feature/vrm1_springbone_runtime

[vrm-1.0][SpringBone] import 時に springbone 実装をスイッチする IVrm10SpringBoneRuntime インターフェース
This commit is contained in:
ousttrue
2024-09-20 20:23:47 +09:00
committed by GitHub
13 changed files with 757 additions and 44 deletions

View File

@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UniGLTF;
using UniGLTF.Utils;
using UnityEngine;
using UnityEngine.Serialization;
@@ -66,12 +68,37 @@ namespace UniVRM10
private UniHumanoid.Humanoid m_humanoid;
private Vrm10Runtime m_runtime;
// 中継用。InitializeAtRuntime でもらって MakeRuntime で使う
private IVrm10SpringBoneRuntime m_springBoneRuntime;
private IReadOnlyDictionary<Transform, TransformState> m_defaultTransformStates;
/// <summary>
/// ControlRig の生成オプション
/// </summary>
private bool m_useControlRig;
public IReadOnlyDictionary<Transform, TransformState> DefaultTransformStates
{
get
{
if (m_defaultTransformStates == null)
{
if (TryGetComponent<RuntimeGltfInstance>(out var gltfInstance))
{
// ランタイムインポートならここに到達してゼロコストになる
m_defaultTransformStates = gltfInstance.InitialTransformStates;
}
else
{
// エディタでプレハブ配置してる奴ならこっちに到達して収集する
m_defaultTransformStates = GetComponentsInChildren<Transform>()
.ToDictionary(tf => tf, tf => new TransformState(tf));
}
}
return m_defaultTransformStates;
}
}
/// <summary>
/// VRM ファイルに記録された Humanoid ボーンに対応します。
/// これは、コントロールリグのボーンとは異なります。
@@ -88,9 +115,17 @@ namespace UniVRM10
}
}
/// <summary>
/// ランタイム情報
/// </summary>
internal Vrm10Runtime MakeRuntime(bool useControlRig)
{
if (m_springBoneRuntime == null)
{
// deafult に fallback
// TODO: scene に配置した prefab に SpringRuntime をカスタムする手段
m_springBoneRuntime = new Vrm10FastSpringboneRuntime();
}
return new Vrm10Runtime(this, useControlRig, m_springBoneRuntime);
}
public Vrm10Runtime Runtime
{
get
@@ -98,15 +133,39 @@ namespace UniVRM10
if (m_runtime == null)
{
if (this == null) throw new MissingReferenceException("instance was destroyed");
m_runtime = new Vrm10Runtime(this, m_useControlRig);
m_runtime = MakeRuntime(m_useControlRig);
}
return m_runtime;
}
}
internal void InitializeAtRuntime(bool useControlRig)
internal void InitializeAtRuntime(
bool useControlRig,
IVrm10SpringBoneRuntime springBoneRuntime,
IReadOnlyDictionary<Transform, TransformState> defaultTransformStates = null
)
{
m_useControlRig = useControlRig;
m_springBoneRuntime = springBoneRuntime;
if (defaultTransformStates != null)
{
m_defaultTransformStates = defaultTransformStates;
}
else
{
if (TryGetComponent<RuntimeGltfInstance>(out var gltfInstance))
{
// ランタイムインポートならここに到達してゼロコストになる
defaultTransformStates = gltfInstance.InitialTransformStates;
}
else
{
// エディタでプレハブ配置してる奴ならこっちに到達して収集する
defaultTransformStates = GetComponentsInChildren<Transform>()
.ToDictionary(tf => tf, tf => new TransformState(tf));
}
}
}
void Start()

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UniGLTF;
using UniGLTF.Utils;
@@ -9,11 +8,15 @@ using UniGLTF.SpringBoneJobs.InputPorts;
namespace UniVRM10
{
public class Vrm10RuntimeSpringBone : IDisposable
/// <summary>
/// FastSpringbone(job + singleton) で動作します。
/// FastSpringBoneService に登録します。
/// FastSpringBoneService.LateUpdate[DefaultExecutionOrder(11010)] で動作します。
/// </summary>
public class Vrm10FastSpringboneRuntime : IVrm10SpringBoneRuntime
{
private readonly Vrm10Instance m_instance;
private readonly IReadOnlyDictionary<Transform, TransformState> m_defaultTransformStates;
private readonly FastSpringBones.FastSpringBoneService m_fastSpringBoneService;
private Vrm10Instance m_instance;
private readonly FastSpringBones.FastSpringBoneService m_fastSpringBoneService = FastSpringBones.FastSpringBoneService.Instance;
private FastSpringBoneSpring[] m_springs;
private Quaternion[] m_initialLocalRotations;
private FastSpringBoneBuffer m_fastSpringBoneBuffer;
@@ -28,26 +31,16 @@ namespace UniVRM10
set => m_fastSpringBoneBuffer.IsSpringBoneEnabled = value;
}
internal Vrm10RuntimeSpringBone(Vrm10Instance instance)
public float DeltaTime => throw new NotImplementedException();
/// <param name="initialTransform">VRMの初期姿勢(T-Pose)状態。instanceがT-Poseから変化していても大丈夫</param>
public void Initialize(Vrm10Instance instance)
{
m_instance = instance;
if (instance.TryGetComponent<RuntimeGltfInstance>(out var gltfInstance))
{
// ランタイムインポートならここに到達してゼロコストになる
m_defaultTransformStates = gltfInstance.InitialTransformStates;
}
else
{
// エディタでプレハブ配置してる奴ならこっちに到達して収集する
m_defaultTransformStates = instance.GetComponentsInChildren<Transform>()
.ToDictionary(tf => tf, tf => new TransformState(tf));
}
// NOTE: FastSpringBoneService は UnitTest などでは動作しない
if (Application.isPlaying)
{
m_fastSpringBoneService = FastSpringBones.FastSpringBoneService.Instance;
ReconstructSpringBone();
}
}
@@ -113,7 +106,7 @@ namespace UniVRM10
private TransformState GetOrAddDefaultTransformState(Transform tf)
{
if (m_defaultTransformStates.TryGetValue(tf, out var defaultTransformState))
if (m_instance.DefaultTransformStates.TryGetValue(tf, out var defaultTransformState))
{
return defaultTransformState;
}
@@ -152,5 +145,10 @@ namespace UniVRM10
// TODO:
}
public void Process()
{
// FastSpringBoneService が実行するので何もしない
}
}
}

View File

@@ -0,0 +1,166 @@
using System;
using System.Linq;
using UniGLTF;
using UniGLTF.Utils;
using UnityEngine;
using UniGLTF.SpringBoneJobs.Blittables;
using UniGLTF.SpringBoneJobs.InputPorts;
using UniGLTF.SpringBoneJobs;
namespace UniVRM10
{
/// <summary>
/// FastSpringbone(job) で動作します。
/// FastSpringBoneService(Singleton)を経由せずに直接実行します。
///
/// シーンに2体以上の vrm-1.0 モデルがある場合は FastSpringBoneService でバッチングする方が効率的です。
/// </summary>
public class Vrm10FastSpringboneRuntimeStandalone : IVrm10SpringBoneRuntime
{
private Vrm10Instance m_instance;
private FastSpringBoneSpring[] m_springs;
private Quaternion[] m_initialLocalRotations;
private FastSpringBoneBuffer m_fastSpringBoneBuffer;
public FastSpringBoneBufferCombiner m_bufferCombiner = new();
private FastSpringBoneScheduler m_fastSpringBoneScheduler;
public Vector3 ExternalForce
{
get => m_fastSpringBoneBuffer.ExternalForce;
set => m_fastSpringBoneBuffer.ExternalForce = value;
}
public bool IsSpringBoneEnabled
{
get => m_fastSpringBoneBuffer.IsSpringBoneEnabled;
set => m_fastSpringBoneBuffer.IsSpringBoneEnabled = value;
}
public float DeltaTime => Time.deltaTime;
public Vrm10FastSpringboneRuntimeStandalone()
{
m_fastSpringBoneScheduler = new(m_bufferCombiner);
}
/// <param name="initialTransform">VRMの初期姿勢(T-Pose)状態。instanceがT-Poseから変化していても大丈夫</param>
public void Initialize(Vrm10Instance instance)
{
m_instance = instance;
// NOTE: FastSpringBoneService は UnitTest などでは動作しない
if (Application.isPlaying)
{
ReconstructSpringBone();
}
}
public void Dispose()
{
m_bufferCombiner.Unregister(m_fastSpringBoneBuffer);
m_fastSpringBoneBuffer.Dispose();
m_fastSpringBoneScheduler.Dispose();
m_bufferCombiner.Dispose();
}
/// <summary>
/// このVRMに紐づくSpringBone関連のバッファを再構築する
/// ランタイム実行時にSpringBoneに対して変更を行いたいときは、このメソッドを明示的に呼ぶ必要がある
/// </summary>
public void ReconstructSpringBone()
{
// release
if (m_fastSpringBoneBuffer != null)
{
m_bufferCombiner.Unregister(m_fastSpringBoneBuffer);
m_fastSpringBoneBuffer.Dispose();
}
// create(Spring情報の再収集。設定変更の反映)
m_springs = m_instance.SpringBone.Springs.Select(spring => new FastSpringBoneSpring
{
center = spring.Center,
colliders = spring.ColliderGroups
.SelectMany(group => group.Colliders)
.Select(collider => new FastSpringBoneCollider
{
Transform = collider.transform,
Collider = new BlittableCollider
{
offset = collider.Offset,
radius = collider.Radius,
tailOrNormal = collider.TailOrNormal,
colliderType = TranslateColliderType(collider.ColliderType)
}
}).ToArray(),
joints = spring.Joints
.Select(joint => new FastSpringBoneJoint
{
Transform = joint.transform,
Joint = new BlittableJointMutable
{
radius = joint.m_jointRadius,
dragForce = joint.m_dragForce,
gravityDir = joint.m_gravityDir,
gravityPower = joint.m_gravityPower,
stiffnessForce = joint.m_stiffnessForce
},
DefaultLocalRotation = GetOrAddDefaultTransformState(joint.transform).LocalRotation,
}).ToArray(),
}).ToArray();
// DOTS buffer 構築
m_fastSpringBoneBuffer = new FastSpringBoneBuffer(m_springs);
m_bufferCombiner.Register(m_fastSpringBoneBuffer);
// reset 用の初期状態の記録
m_initialLocalRotations = m_fastSpringBoneBuffer.Transforms.Select(x => x.localRotation).ToArray();
}
private TransformState GetOrAddDefaultTransformState(Transform tf)
{
if (m_instance.DefaultTransformStates.TryGetValue(tf, out var defaultTransformState))
{
return defaultTransformState;
}
Debug.LogWarning($"{tf.name} does not exist on load.");
return new TransformState(null);
}
private static BlittableColliderType TranslateColliderType(VRM10SpringBoneColliderTypes colliderType)
{
switch (colliderType)
{
case VRM10SpringBoneColliderTypes.Sphere:
return BlittableColliderType.Sphere;
case VRM10SpringBoneColliderTypes.Capsule:
return BlittableColliderType.Capsule;
case VRM10SpringBoneColliderTypes.Plane:
return BlittableColliderType.Plane;
case VRM10SpringBoneColliderTypes.SphereInside:
return BlittableColliderType.SphereInside;
case VRM10SpringBoneColliderTypes.CapsuleInside:
return BlittableColliderType.CapsuleInside;
default:
throw new ArgumentOutOfRangeException();
}
}
public void RestoreInitialTransform()
{
// Spring の joint に対応する transform の回転を初期状態
for (int i = 0; i < m_fastSpringBoneBuffer.Transforms.Length; ++i)
{
var transform = m_fastSpringBoneBuffer.Transforms[i];
transform.localRotation = m_initialLocalRotations[i];
}
// TODO:
}
public void Process()
{
m_fastSpringBoneScheduler.Schedule(DeltaTime).Complete();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b2db989bb92a9a64b98516b30db3902a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -27,7 +27,7 @@ namespace UniVRM10
public IVrm10Constraint[] Constraints { get; }
public Vrm10RuntimeExpression Expression { get; }
public Vrm10RuntimeLookAt LookAt { get; }
public Vrm10RuntimeSpringBone SpringBone { get; }
public IVrm10SpringBoneRuntime SpringBone { get; }
public IVrm10Animation VrmAnimation { get; set; }
[Obsolete("use Vrm10Runtime.SpringBone.ExternalForce")]
@@ -37,7 +37,7 @@ namespace UniVRM10
set { SpringBone.ExternalForce = value; }
}
public Vrm10Runtime(Vrm10Instance instance, bool useControlRig)
public Vrm10Runtime(Vrm10Instance instance, bool useControlRig, IVrm10SpringBoneRuntime springBoneRuntime)
{
if (!Application.isPlaying)
{
@@ -58,7 +58,8 @@ namespace UniVRM10
Constraints = instance.GetComponentsInChildren<IVrm10Constraint>();
LookAt = new Vrm10RuntimeLookAt(instance.Vrm.LookAt, instance.Humanoid, ControlRig);
Expression = new Vrm10RuntimeExpression(instance, LookAt.EyeDirectionApplicable);
SpringBone = new Vrm10RuntimeSpringBone(instance);
SpringBone = springBoneRuntime;
SpringBone.Initialize(instance);
}
public void Dispose()
@@ -128,6 +129,9 @@ namespace UniVRM10
// 5. Apply Expression
// LookAt の角度制限などはこちらで処理されます。
Expression.Process(eyeDirection);
// 6. SpringBone
SpringBone.Process();
}
}
}

View File

@@ -0,0 +1,41 @@
using System;
using UnityEngine;
namespace UniVRM10
{
public interface IVrm10SpringBoneRuntime : IDisposable
{
public void Initialize(Vrm10Instance instance);
/// <summary>
/// 主に singleton のバッチング更新。
/// </summary>
public void ReconstructSpringBone();
/// <summary>
/// initialTransform 状態に復帰。verlet の速度 も 0 に。
/// </summary>
public void RestoreInitialTransform();
/// <summary>
/// deltaTime のカスタマイズポイント。通常は Time.dletaTime
/// </summary>
public float DeltaTime { get; }
/// <summary>
/// 風などの追加の外力を設定する
/// </summary>
public Vector3 ExternalForce { get; set; }
/// <summary>
// SpringBone のランタイムの動作状態を設定する。
// SpringBone の動きを一時停止したいときは false にする。
/// </summary>
public bool IsSpringBoneEnabled { get; set; }
/// <summary>
/// 毎フレーム Vrm10Runtime.Process から呼ばれる。
/// </summary>
public void Process();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 50a24e5a47bb02848abe4d257ffdc7f4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -46,7 +46,8 @@ namespace UniVRM10
IMaterialDescriptorGenerator materialGenerator = null,
VrmMetaInformationCallback vrmMetaInformationCallback = null,
CancellationToken ct = default,
ImporterContextSettings importerContextSettings = null)
ImporterContextSettings importerContextSettings = null,
IVrm10SpringBoneRuntime springboneRuntime = null)
{
awaitCaller ??= Application.isPlaying
? new RuntimeOnlyAwaitCaller()
@@ -67,7 +68,8 @@ namespace UniVRM10
materialGenerator,
vrmMetaInformationCallback,
ct,
importerContextSettings);
importerContextSettings,
springboneRuntime);
}
/// <summary>
@@ -174,7 +176,8 @@ namespace UniVRM10
IMaterialDescriptorGenerator materialGenerator,
VrmMetaInformationCallback vrmMetaInformationCallback,
CancellationToken ct,
ImporterContextSettings importerContextSettings = null)
ImporterContextSettings importerContextSettings = null,
IVrm10SpringBoneRuntime springboneRuntime = null)
{
ct.ThrowIfCancellationRequested();
if (awaitCaller == null)
@@ -192,7 +195,8 @@ namespace UniVRM10
materialGenerator,
vrmMetaInformationCallback,
ct,
importerContextSettings);
importerContextSettings,
springboneRuntime);
if (instance != null)
{
if (ct.IsCancellationRequested)
@@ -218,7 +222,8 @@ namespace UniVRM10
textureDeserializer,
materialGenerator,
vrmMetaInformationCallback,
ct);
ct,
springboneRuntime);
if (migratedInstance != null)
{
if (ct.IsCancellationRequested)
@@ -242,7 +247,8 @@ namespace UniVRM10
IMaterialDescriptorGenerator materialGenerator,
VrmMetaInformationCallback vrmMetaInformationCallback,
CancellationToken ct,
ImporterContextSettings importerContextSettings = null)
ImporterContextSettings importerContextSettings = null,
IVrm10SpringBoneRuntime springboneRuntime = null)
{
ct.ThrowIfCancellationRequested();
if (awaitCaller == null)
@@ -269,7 +275,8 @@ namespace UniVRM10
materialGenerator,
vrmMetaInformationCallback,
ct,
importerContextSettings);
importerContextSettings,
springboneRuntime);
}
private static async Task<Vrm10Instance> TryMigratingFromVrm0XAsync(
@@ -280,7 +287,8 @@ namespace UniVRM10
ITextureDeserializer textureDeserializer,
IMaterialDescriptorGenerator materialGenerator,
VrmMetaInformationCallback vrmMetaInformationCallback,
CancellationToken ct)
CancellationToken ct,
IVrm10SpringBoneRuntime springboneRuntime)
{
ct.ThrowIfCancellationRequested();
if (awaitCaller == null)
@@ -308,7 +316,8 @@ namespace UniVRM10
textureDeserializer,
materialGenerator,
vrmMetaInformationCallback,
ct);
ct,
springboneRuntime: springboneRuntime);
if (migratedVrm10Instance == null)
{
throw new Exception(migrationData?.Message ?? "Failed to load migrated.");
@@ -327,7 +336,8 @@ namespace UniVRM10
IMaterialDescriptorGenerator materialGenerator,
VrmMetaInformationCallback vrmMetaInformationCallback,
CancellationToken ct,
ImporterContextSettings importerContextSettings = null)
ImporterContextSettings importerContextSettings = null,
IVrm10SpringBoneRuntime springboneRuntime = null)
{
ct.ThrowIfCancellationRequested();
if (awaitCaller == null)
@@ -345,7 +355,8 @@ namespace UniVRM10
textureDeserializer: textureDeserializer,
materialGenerator: materialGenerator,
useControlRig: controlRigGenerationOption != ControlRigGenerationOption.None,
settings: importerContextSettings))
settings: importerContextSettings,
springboneRuntime: springboneRuntime))
{
// 1. Load meta information if callback was available.
if (vrmMetaInformationCallback != null)

View File

@@ -24,13 +24,16 @@ namespace UniVRM10
private VRM10Object m_vrmObject;
private List<(ExpressionPreset Preset, VRM10Expression Clip)> m_expressions = new List<(ExpressionPreset, VRM10Expression)>();
private IVrm10SpringBoneRuntime m_springboneRuntime;
public Vrm10Importer(
Vrm10Data vrm,
IReadOnlyDictionary<SubAssetKey, UnityEngine.Object> externalObjectMap = null,
ITextureDeserializer textureDeserializer = null,
IMaterialDescriptorGenerator materialGenerator = null,
bool useControlRig = false,
ImporterContextSettings settings = null
ImporterContextSettings settings = null,
IVrm10SpringBoneRuntime springboneRuntime = null
)
: base(vrm.Data, externalObjectMap, textureDeserializer, settings: settings)
{
@@ -49,6 +52,8 @@ namespace UniVRM10
{
m_externalMap = new Dictionary<SubAssetKey, UnityEngine.Object>();
}
m_springboneRuntime = springboneRuntime ?? new Vrm10FastSpringboneRuntime();
}
static void AssignHumanoid(List<VrmLib.Node> nodes, UniGLTF.Extensions.VRMC_vrm.HumanBone humanBone, VrmLib.HumanoidBones key)
@@ -258,7 +263,7 @@ namespace UniVRM10
// VrmController
var controller = Root.AddComponent<Vrm10Instance>();
controller.InitializeAtRuntime(m_useControlRig);
controller.InitializeAtRuntime(m_useControlRig, m_springboneRuntime);
controller.enabled = false;
// vrm

View File

@@ -32,7 +32,7 @@ namespace UniVRM10.Test
controller.Vrm.Expression.Aa.MaterialColorBindings = src.ToArray();
// ok if no exception
var r = new Vrm10Runtime(controller, useControlRig: false);
var r = controller.MakeRuntime(useControlRig: false);
}
[Test]
@@ -56,7 +56,7 @@ namespace UniVRM10.Test
controller.Vrm.Expression.Aa.MaterialUVBindings = src.ToArray();
// ok if no exception
var r = new Vrm10Runtime(controller, useControlRig: false);
var r = controller.MakeRuntime(useControlRig: false);
}
}
}

View File

@@ -124,6 +124,86 @@ NavMeshSettings:
debug:
m_Flags: 0
m_NavMeshData: {fileID: 0}
--- !u!1 &20563308
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 20563309}
- component: {fileID: 20563311}
- component: {fileID: 20563310}
m_Layer: 5
m_Name: Label
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &20563309
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 20563308}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 522109224}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 9, y: -0.5}
m_SizeDelta: {x: -28, y: -3}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &20563310
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 20563308}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_FontData:
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
m_FontSize: 14
m_FontStyle: 0
m_BestFit: 0
m_MinSize: 10
m_MaxSize: 40
m_Alignment: 0
m_AlignByGeometry: 0
m_RichText: 1
m_HorizontalOverflow: 0
m_VerticalOverflow: 0
m_LineSpacing: 1
m_Text: Singleton
--- !u!222 &20563311
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 20563308}
m_CullTransparentMesh: 0
--- !u!1 &62367394
GameObject:
m_ObjectHideFlags: 0
@@ -1122,6 +1202,8 @@ RectTransform:
- {fileID: 1767738854}
- {fileID: 103723704}
- {fileID: 602093298}
- {fileID: 1346594062}
- {fileID: 522109224}
m_Father: {fileID: 124675794}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
@@ -1506,6 +1588,93 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 491613100}
m_CullTransparentMesh: 0
--- !u!1 &522109223
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 522109224}
- component: {fileID: 522109225}
m_Layer: 5
m_Name: Singleton
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &522109224
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 522109223}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 2052921329}
- {fileID: 20563309}
m_Father: {fileID: 339774397}
m_RootOrder: 19
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 162, y: 20}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &522109225
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 522109223}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 9085046f02f69544eb97fd06b6048fe2, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Navigation:
m_Mode: 3
m_WrapAround: 0
m_SelectOnUp: {fileID: 0}
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 1
m_Colors:
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
m_ColorMultiplier: 1
m_FadeDuration: 0.1
m_SpriteState:
m_HighlightedSprite: {fileID: 0}
m_PressedSprite: {fileID: 0}
m_SelectedSprite: {fileID: 0}
m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
m_NormalTrigger: Normal
m_HighlightedTrigger: Highlighted
m_PressedTrigger: Pressed
m_SelectedTrigger: Highlighted
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 2052921330}
toggleTransition: 1
graphic: {fileID: 1039332177}
m_Group: {fileID: 0}
onValueChanged:
m_PersistentCalls:
m_Calls: []
m_IsOn: 1
--- !u!1 &587234268
GameObject:
m_ObjectHideFlags: 0
@@ -3592,6 +3761,82 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1037763548}
m_CullTransparentMesh: 0
--- !u!1 &1039332175
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1039332176}
- component: {fileID: 1039332178}
- component: {fileID: 1039332177}
m_Layer: 5
m_Name: Checkmark
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1039332176
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1039332175}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 2052921329}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 20, y: 20}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1039332177
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1039332175}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10901, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!222 &1039332178
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1039332175}
m_CullTransparentMesh: 0
--- !u!1 &1045380261
GameObject:
m_ObjectHideFlags: 0
@@ -5228,6 +5473,86 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1322834809}
m_CullTransparentMesh: 0
--- !u!1 &1346594061
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1346594062}
- component: {fileID: 1346594064}
- component: {fileID: 1346594063}
m_Layer: 5
m_Name: _SpringBone_
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1346594062
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1346594061}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 339774397}
m_RootOrder: 18
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 178, y: 30}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1346594063
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1346594061}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_FontData:
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
m_FontSize: 14
m_FontStyle: 1
m_BestFit: 0
m_MinSize: 10
m_MaxSize: 40
m_Alignment: 4
m_AlignByGeometry: 0
m_RichText: 1
m_HorizontalOverflow: 0
m_VerticalOverflow: 0
m_LineSpacing: 1
m_Text: SpringBone
--- !u!222 &1346594064
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1346594061}
m_CullTransparentMesh: 0
--- !u!1 &1407428956
GameObject:
m_ObjectHideFlags: 0
@@ -7382,6 +7707,83 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2010083453}
m_CullTransparentMesh: 0
--- !u!1 &2052921328
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2052921329}
- component: {fileID: 2052921331}
- component: {fileID: 2052921330}
m_Layer: 5
m_Name: Background
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &2052921329
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2052921328}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 1039332176}
m_Father: {fileID: 522109224}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 10, y: -10}
m_SizeDelta: {x: 20, y: 20}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &2052921330
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2052921328}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!222 &2052921331
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2052921328}
m_CullTransparentMesh: 0
--- !u!1 &2055567528
GameObject:
m_ObjectHideFlags: 0

View File

@@ -44,6 +44,9 @@ namespace UniVRM10.VRM10Viewer
[SerializeField]
Toggle m_useAsync = default;
[SerializeField]
Toggle m_useSingelton = default;
[SerializeField]
GameObject m_target = default;
@@ -267,6 +270,7 @@ namespace UniVRM10.VRM10Viewer
m_enableAutoBlink = toggles.First(x => x.name == "EnableAutoBlink");
m_enableAutoExpression = toggles.First(x => x.name == "EnableAutoExpression");
m_useAsync = toggles.First(x => x.name == "UseAsync");
m_useSingelton = toggles.First(x => x.name == "UseSingleton");
#if UNITY_2022_3_OR_NEWER
var texts = GameObject.FindObjectsByType<Text>(FindObjectsSortMode.InstanceID);
@@ -542,7 +546,8 @@ namespace UniVRM10.VRM10Viewer
showMeshes: false,
awaitCaller: m_useAsync.enabled ? new RuntimeOnlyAwaitCaller() : new ImmediateCaller(),
vrmMetaInformationCallback: m_texts.UpdateMeta,
ct: cancellationToken);
ct: cancellationToken,
springboneRuntime: m_useSingelton.isOn ? new Vrm10FastSpringboneRuntime() : new Vrm10FastSpringboneRuntimeStandalone());
if (cancellationToken.IsCancellationRequested)
{
UnityObjectDestroyer.DestroyRuntimeOrEditor(vrm10Instance.gameObject);