mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-09-09 04:19:42 -05:00
Add VRM FastSpringBone support
This commit is contained in:
27
Assets/VRM/Runtime/SpringBone/FastSpringBoneDisposer.cs
Normal file
27
Assets/VRM/Runtime/SpringBone/FastSpringBoneDisposer.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VRM
|
||||
{
|
||||
/// <summary>
|
||||
/// FastSpringBoneに関連して、特定のGameObjectと紐付いたIDisposableの破棄を担当するクラス
|
||||
/// </summary>
|
||||
public sealed class FastSpringBoneDisposer : MonoBehaviour
|
||||
{
|
||||
private readonly List<IDisposable> _disposables = new List<IDisposable>();
|
||||
|
||||
public void Add(IDisposable disposable)
|
||||
{
|
||||
_disposables.Add(disposable);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
foreach (var disposable in _disposables)
|
||||
{
|
||||
disposable.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0b96d696de06439e97ac33ed2d890c88
|
||||
timeCreated: 1632893490
|
||||
130
Assets/VRM/Runtime/SpringBone/FastSpringBoneReplacer.cs
Normal file
130
Assets/VRM/Runtime/SpringBone/FastSpringBoneReplacer.cs
Normal file
@@ -0,0 +1,130 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using VRM.FastSpringBones.Blittables;
|
||||
using VRM.FastSpringBones.Components;
|
||||
using VRMShaders;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace VRM
|
||||
{
|
||||
/// <summary>
|
||||
/// 指定されたGameObject内にあるSpringBoneをFastSpringBoneに差し替えるユーティリティ
|
||||
/// </summary>
|
||||
public static class FastSpringBoneReplacer
|
||||
{
|
||||
public static async Task ReplaceAsync(GameObject gameObject, IAwaitCaller awaitCaller = null, CancellationToken token = default)
|
||||
{
|
||||
var service = FastSpringBoneService.Instance;
|
||||
var springBones = gameObject.GetComponentsInChildren<VRMSpringBone>();
|
||||
var disposer = gameObject.AddComponent<FastSpringBoneDisposer>();
|
||||
|
||||
// VRMSpringBoneで動いた後の状態がFastSpringBoneの初期状態にならないようにするためawait UniTask.Yield()する前にVRMSpringBoneをdisableにしておく
|
||||
foreach (var springBone in springBones)
|
||||
{
|
||||
springBone.enabled = false;
|
||||
};
|
||||
|
||||
if (awaitCaller != null)
|
||||
{
|
||||
await awaitCaller.NextFrame();
|
||||
token.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
var vrmColliderGroups = gameObject.GetComponentsInChildren<VRMSpringBoneColliderGroup>();
|
||||
var colliderGroupDictionary = new Dictionary<VRMSpringBoneColliderGroup, FastSpringBoneColliderGroup>();
|
||||
|
||||
// Colliderを差し替える
|
||||
foreach (var vrmColliderGroup in vrmColliderGroups)
|
||||
{
|
||||
if (awaitCaller != null)
|
||||
{
|
||||
await awaitCaller.NextFrame();
|
||||
token.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
var fastSpringBoneCollider = vrmColliderGroup.gameObject.AddComponent<FastSpringBoneColliderGroup>();
|
||||
fastSpringBoneCollider.Initialize(
|
||||
service.TransformRegistry,
|
||||
vrmColliderGroup.Colliders
|
||||
.Select(data => new BlittableCollider(data.Offset, data.Radius))
|
||||
.ToArray()
|
||||
);
|
||||
colliderGroupDictionary[vrmColliderGroup] = fastSpringBoneCollider;
|
||||
}
|
||||
|
||||
var springRootBones =
|
||||
(
|
||||
from springBone in springBones
|
||||
from rootBone in springBone.RootBones
|
||||
select (springBone, rootBone)
|
||||
).ToList();
|
||||
|
||||
for (var i = 0; i < springRootBones.Count; i++)
|
||||
{
|
||||
var current = springRootBones[i];
|
||||
|
||||
// 他のRootBoneのどれかが、自分の親(もしくは同じTransform)なら自分自身を削除する
|
||||
if (springRootBones
|
||||
.Where(other => other != current)
|
||||
.Any(other => current.rootBone.IsChildOf(other.rootBone)))
|
||||
{
|
||||
springRootBones.RemoveAt(i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
if (awaitCaller != null)
|
||||
{
|
||||
await awaitCaller.NextFrame();
|
||||
token.ThrowIfCancellationRequested();
|
||||
}
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
foreach (var (vrmSpringBone, rootBoneTransform) in springRootBones)
|
||||
{
|
||||
// FastSpringRootBoneに差し替える
|
||||
var fastSpringRootBone =
|
||||
new FastSpringRootBone(
|
||||
service.TransformRegistry,
|
||||
rootBoneTransform,
|
||||
service.RootBoneRegistry,
|
||||
service.ColliderGroupRegistry);
|
||||
disposer.Add(fastSpringRootBone);
|
||||
|
||||
var colliderGroups =
|
||||
vrmSpringBone.ColliderGroups != null
|
||||
? vrmSpringBone.ColliderGroups.Select(group => colliderGroupDictionary[@group]).ToArray()
|
||||
: Array.Empty<FastSpringBoneColliderGroup>();
|
||||
|
||||
fastSpringRootBone.Initialize(
|
||||
vrmSpringBone.m_gravityPower,
|
||||
vrmSpringBone.m_gravityDir,
|
||||
vrmSpringBone.m_dragForce,
|
||||
vrmSpringBone.m_stiffnessForce,
|
||||
colliderGroups,
|
||||
vrmSpringBone.m_hitRadius,
|
||||
vrmSpringBone.m_center
|
||||
);
|
||||
|
||||
Object.Destroy(vrmSpringBone);
|
||||
|
||||
if (awaitCaller != null)
|
||||
{
|
||||
await awaitCaller.NextFrame();
|
||||
token.ThrowIfCancellationRequested();
|
||||
}
|
||||
token.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
// Colliderを削除
|
||||
foreach (var vrmSpringBoneColliderGroup in vrmColliderGroups)
|
||||
{
|
||||
Object.Destroy(vrmSpringBoneColliderGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/VRM/Runtime/SpringBone/FastSpringBoneReplacer.cs.meta
Normal file
11
Assets/VRM/Runtime/SpringBone/FastSpringBoneReplacer.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a344a05a3634bac419be8a218d8b85d6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
54
Assets/VRM/Runtime/SpringBone/FastSpringBoneService.cs
Normal file
54
Assets/VRM/Runtime/SpringBone/FastSpringBoneService.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using UnityEngine;
|
||||
using VRM.FastSpringBones.Components;
|
||||
using VRM.FastSpringBones.Registries;
|
||||
|
||||
namespace VRM
|
||||
{
|
||||
/// <summary>
|
||||
/// Scene 上に単一で存在する、FastSpringBone の ServiceLocator 兼 EntryPoint
|
||||
/// </summary>
|
||||
public class FastSpringBoneService : MonoBehaviour
|
||||
{
|
||||
public RootBoneRegistry RootBoneRegistry { get; private set; }
|
||||
public TransformRegistry TransformRegistry { get; private set; }
|
||||
public ColliderGroupRegistry ColliderGroupRegistry { get; private set; }
|
||||
public FastSpringBoneScheduler FastSpringBoneScheduler { get; private set; }
|
||||
|
||||
private static FastSpringBoneService _instance;
|
||||
|
||||
public static FastSpringBoneService Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_instance)
|
||||
{
|
||||
var gameObject = new GameObject("FastSpringBone Service");
|
||||
DontDestroyOnLoad(gameObject);
|
||||
_instance = gameObject.AddComponent<FastSpringBoneService>();
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 専有しているインスタンスを破棄する
|
||||
/// </summary>
|
||||
public static void Free()
|
||||
{
|
||||
Destroy(_instance.gameObject);
|
||||
_instance = null;
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
RootBoneRegistry = new RootBoneRegistry();
|
||||
TransformRegistry = new TransformRegistry();
|
||||
ColliderGroupRegistry = new ColliderGroupRegistry();
|
||||
FastSpringBoneScheduler = gameObject.AddComponent<FastSpringBoneScheduler>();
|
||||
FastSpringBoneScheduler.Initialize(
|
||||
RootBoneRegistry,
|
||||
TransformRegistry,
|
||||
ColliderGroupRegistry);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7c3edad580b54158b37169025a1e207d
|
||||
timeCreated: 1632894654
|
||||
@@ -5,7 +5,8 @@
|
||||
"GUID:8d76e605759c3f64a957d63ef96ada7c",
|
||||
"GUID:da3e51d19d51a544fa14d43fee843098",
|
||||
"GUID:301b251fd9834274c9228e0532f444f7",
|
||||
"GUID:a9bc101fb0471f94a8f99fd242fdd934"
|
||||
"GUID:a9bc101fb0471f94a8f99fd242fdd934",
|
||||
"GUID:ac229b552c3025545b074203f857547c"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
||||
Reference in New Issue
Block a user