mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-06-03 06:24:46 -05:00
Merge pull request #1263 from notargs/feature/fast_spring_bone
Add FastSpringBone
This commit is contained in:
commit
ee8f8cef72
8
Assets/VRM/Runtime/FastSpringBone.meta
Normal file
8
Assets/VRM/Runtime/FastSpringBone.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: cf09adfffebbff24eb2185e1d9b5b0a9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/VRM/Runtime/FastSpringBone/Blittables.meta
Normal file
8
Assets/VRM/Runtime/FastSpringBone/Blittables.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b2c4f2f05fcb4fb49be96d3b99236983
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace VRM.FastSpringBones.Blittables
|
||||
{
|
||||
/// <summary>
|
||||
/// VRMSpringBoneのSphereColliderをBlittableにしたもの
|
||||
/// 位置情報は親であるColliderGroupが持つ
|
||||
/// </summary>
|
||||
public readonly struct BlittableCollider
|
||||
{
|
||||
public Vector3 Offset { get; }
|
||||
public float Radius { get; }
|
||||
|
||||
public BlittableCollider(Vector3 offset, float radius)
|
||||
{
|
||||
Offset = offset;
|
||||
Radius = radius;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: cc94117758e24aca9cf44d3f930fdcb0
|
||||
timeCreated: 1550209189
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
using Unity.Collections;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
|
||||
namespace VRM.FastSpringBones.Blittables
|
||||
{
|
||||
/// <summary>
|
||||
/// VRMSpringBoneのColliderGroupをBlittableにしたもの
|
||||
/// </summary>
|
||||
public readonly struct BlittableColliderGroup
|
||||
{
|
||||
public BlittableColliders Colliders { get; }
|
||||
public unsafe BlittableTransform* Transform { get; }
|
||||
|
||||
public unsafe BlittableColliderGroup(NativeArray<BlittableCollider> colliders, BlittableTransform* transform)
|
||||
{
|
||||
Colliders = new BlittableColliders((BlittableCollider*)colliders.GetUnsafePtr(), colliders.Length);
|
||||
Transform = transform;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9bceae7ad8eb4021912778484d1b2ebc
|
||||
timeCreated: 1550223602
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace VRM.FastSpringBones.Blittables
|
||||
{
|
||||
/// <summary>
|
||||
/// BlittableColliderGroupのポインタの配列
|
||||
/// </summary>
|
||||
public readonly unsafe struct BlittableColliderGroups
|
||||
{
|
||||
private readonly BlittableColliderGroup* _data;
|
||||
public int Length { get; }
|
||||
|
||||
public BlittableColliderGroup this[int i] => _data[i];
|
||||
|
||||
public void DrawGizmos()
|
||||
{
|
||||
for (var i = 0; i < Length; i++)
|
||||
{
|
||||
var group = this[i];
|
||||
var colliders = group.Colliders;
|
||||
for (var j = 0; j < colliders.Count; ++j)
|
||||
{
|
||||
Gizmos.DrawWireSphere(group.Transform->WorldPosition, colliders[j].Radius);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BlittableColliderGroups(BlittableColliderGroup* data, int length)
|
||||
{
|
||||
_data = data;
|
||||
Length = length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 61f56040664345a8aba5309e7714f8f2
|
||||
timeCreated: 1550563011
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
namespace VRM.FastSpringBones.Blittables
|
||||
{
|
||||
/// <summary>
|
||||
/// BlittableColliderのポインタの配列
|
||||
/// </summary>
|
||||
public unsafe struct BlittableColliders
|
||||
{
|
||||
private readonly BlittableCollider* _colliders;
|
||||
public int Count { get; }
|
||||
|
||||
public BlittableCollider this[int i] => _colliders[i];
|
||||
|
||||
public BlittableColliders(BlittableCollider* colliders, int count)
|
||||
{
|
||||
_colliders = colliders;
|
||||
Count = count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 07087baebec34286ac230d58cd0163d2
|
||||
timeCreated: 1550562383
|
||||
149
Assets/VRM/Runtime/FastSpringBone/Blittables/BlittablePoint.cs
Normal file
149
Assets/VRM/Runtime/FastSpringBone/Blittables/BlittablePoint.cs
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace VRM.FastSpringBones.Blittables
|
||||
{
|
||||
/// <summary>
|
||||
/// VRMSpringBoneLogicをBlittableにしたもの
|
||||
/// ベルレ積分など、コアな計算を行う
|
||||
/// </summary>
|
||||
public unsafe struct BlittablePoint
|
||||
{
|
||||
private readonly float _length;
|
||||
private readonly Quaternion _localRotation;
|
||||
private readonly Vector3 _boneAxis;
|
||||
private readonly float _radius;
|
||||
private Vector3 _prevPosition;
|
||||
|
||||
private readonly BlittableColliderGroups* _blittableColliderGroups;
|
||||
private readonly BlittableTransform* _center;
|
||||
|
||||
public Vector3 CurrentPosition { get; private set; }
|
||||
|
||||
private readonly BlittableTransform* _transform;
|
||||
|
||||
public BlittablePoint(
|
||||
Transform transform,
|
||||
float radius,
|
||||
BlittableTransform* center,
|
||||
BlittableColliderGroups* blittableColliderGroups,
|
||||
BlittableTransform* blittableTransform)
|
||||
{
|
||||
Vector3 localPosition;
|
||||
if (transform.childCount == 0)
|
||||
{
|
||||
var delta = transform.position - transform.parent.position;
|
||||
var childPosition = transform.position + delta.normalized * 0.07f;
|
||||
localPosition = transform.worldToLocalMatrix.MultiplyPoint(childPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
var firstChild = transform.GetChild(0);
|
||||
var scale = firstChild.lossyScale;
|
||||
localPosition = firstChild.localPosition;
|
||||
localPosition.x *= scale.x;
|
||||
localPosition.y *= scale.y;
|
||||
localPosition.z *= scale.z;
|
||||
}
|
||||
|
||||
var worldChildPosition = (Vector3)transform.TransformPoint(localPosition);
|
||||
_prevPosition = CurrentPosition = center != null ? center->LocalToWorld.inverse.MultiplyPoint3x4(worldChildPosition) : worldChildPosition;
|
||||
|
||||
_localRotation = transform.localRotation;
|
||||
_boneAxis = localPosition.normalized;
|
||||
_length = localPosition.magnitude;
|
||||
_radius = radius;
|
||||
_blittableColliderGroups = blittableColliderGroups;
|
||||
_transform = blittableTransform;
|
||||
_center = center;
|
||||
}
|
||||
|
||||
public void Update(float stiffnessForce, float dragForce, Vector3 external)
|
||||
{
|
||||
// 親のRotationが変わっている可能性があるので更新する
|
||||
_transform->UpdateLocalToWorldMatrix();
|
||||
|
||||
Vector3 currentPosition;
|
||||
Vector3 prevPosition;
|
||||
|
||||
if (_center == null)
|
||||
{
|
||||
currentPosition = CurrentPosition;
|
||||
prevPosition = _prevPosition;
|
||||
}
|
||||
else
|
||||
{
|
||||
var centerLocalToWorld = _center->LocalToWorld;
|
||||
currentPosition = centerLocalToWorld.MultiplyPoint3x4(CurrentPosition);
|
||||
prevPosition = centerLocalToWorld.MultiplyPoint3x4(_prevPosition);
|
||||
}
|
||||
|
||||
// verlet積分で次の位置を計算
|
||||
var nextPosition = currentPosition
|
||||
+ (currentPosition - prevPosition) * (1.0f - dragForce) // 前フレームの移動を継続する(減衰もあるよ)
|
||||
+ _transform->ParentWorldRotation * _localRotation * _boneAxis * stiffnessForce // 親の回転による子ボーンの移動目標
|
||||
+ external; // 外力による移動量
|
||||
|
||||
// 長さをboneLengthに強制
|
||||
var position = _transform->WorldPosition;
|
||||
nextPosition = position + (nextPosition - position).normalized * _length;
|
||||
|
||||
nextPosition = Collision(nextPosition, position);
|
||||
|
||||
if (_center == null)
|
||||
{
|
||||
_prevPosition = currentPosition;
|
||||
CurrentPosition = nextPosition;
|
||||
}
|
||||
else
|
||||
{
|
||||
var centerWorldToLocal = _center->LocalToWorld.inverse;
|
||||
_prevPosition = centerWorldToLocal.MultiplyPoint3x4(currentPosition);
|
||||
CurrentPosition = centerWorldToLocal.MultiplyPoint3x4(nextPosition);
|
||||
}
|
||||
|
||||
//回転を適用
|
||||
_transform->SetWorldRotation(ApplyRotation(nextPosition));
|
||||
}
|
||||
|
||||
private Vector3 Collision(Vector3 nextPosition, Vector3 position)
|
||||
{
|
||||
for (var i = 0; i < _blittableColliderGroups->Length; ++i)
|
||||
{
|
||||
var colliderGroup = (*_blittableColliderGroups)[i];
|
||||
|
||||
for (var j = 0; j < colliderGroup.Colliders.Count; ++j)
|
||||
{
|
||||
var collider = colliderGroup.Colliders[j];
|
||||
var colliderPosition = colliderGroup.Transform->TransformPoint(collider.Offset);
|
||||
var r = _radius + collider.Radius;
|
||||
|
||||
if (!((nextPosition - colliderPosition).sqrMagnitude <= (r * r))) continue;
|
||||
|
||||
// ヒット。Colliderの半径方向に押し出す
|
||||
var normal = (nextPosition - colliderPosition).normalized;
|
||||
var posFromCollider = colliderPosition + normal * (_radius + collider.Radius);
|
||||
|
||||
// 長さをboneLengthに強制
|
||||
nextPosition = position + (posFromCollider - position).normalized * _length;
|
||||
}
|
||||
}
|
||||
return nextPosition;
|
||||
}
|
||||
|
||||
private static Quaternion FromToRotation(Vector3 from, Vector3 to)
|
||||
=> Quaternion.AxisAngle(
|
||||
angle: Mathf.Acos(Mathf.Clamp(Vector3.Dot(from.normalized, to.normalized), -1f, 1f)),
|
||||
axis: Vector3.Cross(from, to).normalized
|
||||
);
|
||||
|
||||
private Quaternion ApplyRotation(Vector3 nextTail)
|
||||
{
|
||||
var rotation = _transform->ParentWorldRotation * _localRotation;
|
||||
return
|
||||
FromToRotation(
|
||||
rotation * _boneAxis,
|
||||
nextTail - _transform->WorldPosition) *
|
||||
rotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f3f0fc54e34944c892cec2b1e86de7d7
|
||||
timeCreated: 1549430605
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
namespace VRM.FastSpringBones.Blittables
|
||||
{
|
||||
/// <summary>
|
||||
/// BlittablePointのポインタの配列
|
||||
/// </summary>
|
||||
public unsafe struct BlittablePoints
|
||||
{
|
||||
private readonly BlittablePoint* _points;
|
||||
public int Count { get; }
|
||||
|
||||
public BlittablePoint this[int i]
|
||||
{
|
||||
get => _points[i];
|
||||
set => _points[i] = value;
|
||||
}
|
||||
|
||||
public BlittablePoints(BlittablePoint* points, int count)
|
||||
{
|
||||
_points = points;
|
||||
Count = count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0c39cdb389d141bbb084030dd8ebfe8b
|
||||
timeCreated: 1550721598
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace VRM.FastSpringBones.Blittables
|
||||
{
|
||||
/// <summary>
|
||||
/// 1本の毛束を示すBlittable型
|
||||
/// </summary>
|
||||
public unsafe readonly struct BlittableRootBone
|
||||
{
|
||||
private readonly float _gravityPower;
|
||||
private readonly Vector3 _gravityDir;
|
||||
private readonly float _dragForce;
|
||||
private readonly float _stiffnessForce;
|
||||
private readonly BlittablePoints* _blittablePoints;
|
||||
|
||||
public void DrawGizmos()
|
||||
{
|
||||
for (var i = 0; i < _blittablePoints->Count; i++)
|
||||
{
|
||||
var point = (*_blittablePoints)[i];
|
||||
Gizmos.DrawWireSphere(point.CurrentPosition, 0.05f);
|
||||
}
|
||||
for (var i = 0; i < _blittablePoints->Count - 1; i++)
|
||||
{
|
||||
var point1 = (*_blittablePoints)[i];
|
||||
var point2 = (*_blittablePoints)[i + 1];
|
||||
Gizmos.DrawLine(point1.CurrentPosition, point2.CurrentPosition);
|
||||
}
|
||||
}
|
||||
|
||||
public BlittableRootBone(
|
||||
float gravityPower,
|
||||
Vector3 gravityDir,
|
||||
float dragForce,
|
||||
float stiffnessForce,
|
||||
BlittablePoints* blittablePoints)
|
||||
{
|
||||
_gravityPower = gravityPower;
|
||||
_gravityDir = gravityDir;
|
||||
_dragForce = dragForce;
|
||||
_stiffnessForce = stiffnessForce;
|
||||
_blittablePoints = blittablePoints;
|
||||
}
|
||||
|
||||
public void Update(float deltaTime)
|
||||
{
|
||||
var stiffness = _stiffnessForce * deltaTime;
|
||||
var external = _gravityDir * (_gravityPower * deltaTime);
|
||||
for (var i = 0; i < _blittablePoints->Count; i++)
|
||||
{
|
||||
var point = (*_blittablePoints)[i];
|
||||
|
||||
// Pointを更新
|
||||
point.Update(
|
||||
stiffness,
|
||||
_dragForce,
|
||||
external
|
||||
);
|
||||
|
||||
(*_blittablePoints)[i] = point;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bc470487e0a546f087709dbab3c7a6f1
|
||||
timeCreated: 1549952425
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.Jobs;
|
||||
|
||||
namespace VRM.FastSpringBones.Blittables
|
||||
{
|
||||
/// <summary>
|
||||
/// Transformの必要な機能だけを絞り、Blittableに対応させたクラス
|
||||
/// </summary>
|
||||
public unsafe struct BlittableTransform
|
||||
{
|
||||
private readonly BlittableTransform* _parent;
|
||||
private Quaternion _worldRotation;
|
||||
private Vector3 _localPosition;
|
||||
private Vector3 _localScale;
|
||||
private Quaternion _localRotation;
|
||||
private Matrix4x4 _localToWorld;
|
||||
|
||||
public Vector3 WorldPosition { get; private set; }
|
||||
|
||||
public void SetWorldRotation(Quaternion rotation)
|
||||
{
|
||||
var parentWorldRotation = ParentWorldRotation;
|
||||
_localRotation = Quaternion.Inverse(parentWorldRotation) * rotation;
|
||||
UpdateLocalToWorldMatrix();
|
||||
}
|
||||
|
||||
public Matrix4x4 LocalToWorld => _localToWorld;
|
||||
|
||||
private Matrix4x4 LocalTransform => Matrix4x4.TRS(_localPosition, _localRotation, _localScale);
|
||||
|
||||
public Quaternion ParentWorldRotation => _parent != null ? _parent->_worldRotation : Quaternion.identity;
|
||||
|
||||
public BlittableTransform(BlittableTransform* parent, Transform transform)
|
||||
{
|
||||
_parent = parent;
|
||||
|
||||
WorldPosition = transform.position;
|
||||
_worldRotation = transform.rotation;
|
||||
_localPosition = transform.localPosition;
|
||||
_localRotation = transform.localRotation;
|
||||
_localScale = transform.localScale;
|
||||
|
||||
_localToWorld = transform.localToWorldMatrix;
|
||||
}
|
||||
|
||||
public void PullFrom(TransformAccess transform)
|
||||
{
|
||||
WorldPosition = transform.position;
|
||||
_worldRotation = transform.rotation;
|
||||
_localPosition = transform.localPosition;
|
||||
_localRotation = transform.localRotation;
|
||||
_localScale = transform.localScale;
|
||||
|
||||
_localToWorld = transform.localToWorldMatrix;
|
||||
}
|
||||
|
||||
public void PushTo(TransformAccess transform)
|
||||
{
|
||||
transform.localPosition = _localPosition;
|
||||
transform.localRotation = _localRotation;
|
||||
}
|
||||
|
||||
public Vector3 TransformPoint(Vector3 offset) => _localToWorld.MultiplyPoint3x4(offset);
|
||||
|
||||
public void UpdateLocalToWorldMatrix()
|
||||
{
|
||||
_localToWorld = _parent == null ? LocalTransform : _parent->_localToWorld * LocalTransform;
|
||||
WorldPosition = _localToWorld.MultiplyPoint3x4(Vector3.zero);
|
||||
_worldRotation = _localToWorld.rotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bffbbf422e984d028cd82c11f2ca00b1
|
||||
timeCreated: 1550544819
|
||||
8
Assets/VRM/Runtime/FastSpringBone/Components.meta
Normal file
8
Assets/VRM/Runtime/FastSpringBone/Components.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 89d63c6c8787b9a4c80df0fb18aa3d43
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
using UnityEngine;
|
||||
using VRM.FastSpringBones.Blittables;
|
||||
using VRM.FastSpringBones.NativeWrappers;
|
||||
using VRM.FastSpringBones.Registries;
|
||||
|
||||
namespace VRM.FastSpringBones.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// VRMSpringBoneColliderGroupに対応したクラス
|
||||
/// バッファの作成も行う
|
||||
/// </summary>
|
||||
public sealed unsafe class FastSpringBoneColliderGroup : MonoBehaviour
|
||||
{
|
||||
private NativeTransform _nativeTransform;
|
||||
private NativeColliderGroup _nativeColliderGroup;
|
||||
|
||||
public BlittableColliderGroup* ColliderGroupPtr => _nativeColliderGroup.GetUnsafePtr();
|
||||
|
||||
public void Initialize(TransformRegistry transformRegistry, BlittableCollider[] colliders)
|
||||
{
|
||||
_nativeTransform = new NativeTransform(transformRegistry, TransformSynchronizationType.PullOnly, transform);
|
||||
_nativeColliderGroup = new NativeColliderGroup(colliders, _nativeTransform);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
_nativeTransform?.Dispose();
|
||||
_nativeColliderGroup?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2c6ab135b4b945ee9d75c5476ea6bcc0
|
||||
timeCreated: 1550213674
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
using Unity.Jobs;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Profiling;
|
||||
using VRM.FastSpringBones.Registries;
|
||||
using VRM.FastSpringBones.Schedulers;
|
||||
|
||||
namespace VRM.FastSpringBones.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Jobを連続して発火させるComponent
|
||||
/// シーンに1つだけあればいい
|
||||
/// </summary>
|
||||
[DefaultExecutionOrder(11000)]
|
||||
public sealed class FastSpringBoneScheduler : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private bool showGizmos;
|
||||
|
||||
private CustomSampler _updateSampler;
|
||||
|
||||
private PullTransformJobScheduler _pullTransformJobScheduler;
|
||||
private PushTransformJobScheduler _pushTransformJobScheduler;
|
||||
private UpdateSpringBoneJobScheduler _updateSpringBoneJobScheduler;
|
||||
|
||||
private RootBoneRegistry _rootBoneRegistry;
|
||||
private ColliderGroupRegistry _colliderGroupRegistry;
|
||||
|
||||
private JobHandle _prevJobHandle;
|
||||
|
||||
public bool ShowGizmos { get => showGizmos; set => showGizmos = value; }
|
||||
|
||||
public void Initialize(
|
||||
RootBoneRegistry rootBoneRegistry,
|
||||
TransformRegistry transformRegistry,
|
||||
ColliderGroupRegistry colliderGroupRegistry)
|
||||
{
|
||||
_rootBoneRegistry = rootBoneRegistry;
|
||||
_colliderGroupRegistry = colliderGroupRegistry;
|
||||
|
||||
_updateSampler = CustomSampler.Create("FastSpringBone(Update)");
|
||||
|
||||
_pullTransformJobScheduler = new PullTransformJobScheduler(transformRegistry);
|
||||
_pushTransformJobScheduler = new PushTransformJobScheduler(transformRegistry);
|
||||
_updateSpringBoneJobScheduler = new UpdateSpringBoneJobScheduler(_rootBoneRegistry);
|
||||
|
||||
_rootBoneRegistry.SubscribeOnValueChanged(OnRootBoneChanged);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
_rootBoneRegistry.UnSubscribeOnValueChanged(OnRootBoneChanged);
|
||||
_prevJobHandle.Complete();
|
||||
|
||||
_pullTransformJobScheduler.Dispose();
|
||||
_pushTransformJobScheduler.Dispose();
|
||||
_updateSpringBoneJobScheduler.Dispose();
|
||||
}
|
||||
|
||||
private void OnRootBoneChanged()
|
||||
{
|
||||
_prevJobHandle.Complete();
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnDrawGizmos()
|
||||
{
|
||||
if (!ShowGizmos) return;
|
||||
|
||||
_prevJobHandle.Complete();
|
||||
|
||||
Gizmos.color = Color.blue;
|
||||
foreach (var rootBoneWrapper in _rootBoneRegistry.Items)
|
||||
{
|
||||
rootBoneWrapper.Value.DrawGizmos();
|
||||
}
|
||||
|
||||
Gizmos.color = Color.yellow;
|
||||
foreach (var colliderGroup in _colliderGroupRegistry.Items)
|
||||
{
|
||||
colliderGroup.DrawGizmos();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
_updateSampler.Begin();
|
||||
|
||||
_prevJobHandle.Complete();
|
||||
|
||||
var tempJobHandle = default(JobHandle);
|
||||
tempJobHandle = _pullTransformJobScheduler.Schedule(tempJobHandle);
|
||||
tempJobHandle = _updateSpringBoneJobScheduler.Schedule(tempJobHandle);
|
||||
tempJobHandle = _pushTransformJobScheduler.Schedule(tempJobHandle);
|
||||
|
||||
_prevJobHandle = tempJobHandle;
|
||||
|
||||
_updateSampler.End();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2ea019701873487a8533c05f0daa1b37
|
||||
timeCreated: 1549521562
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using VRM.FastSpringBones.Blittables;
|
||||
using VRM.FastSpringBones.NativeWrappers;
|
||||
using VRM.FastSpringBones.Registries;
|
||||
|
||||
namespace VRM.FastSpringBones.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// SpringBoneの1本の毛束の処理を担当するクラス
|
||||
/// </summary>
|
||||
public sealed class FastSpringRootBone : IDisposable
|
||||
{
|
||||
private readonly TransformRegistry _transformRegistry;
|
||||
private readonly RootBoneRegistry _rootBoneRegistry;
|
||||
private readonly ColliderGroupRegistry _colliderGroupRegistry;
|
||||
private readonly Transform _transform;
|
||||
|
||||
private float _radius;
|
||||
private NativeTransform _center;
|
||||
|
||||
private IReadOnlyDictionary<Transform, int> _transformIndexMap;
|
||||
private NativeColliderGroups _nativeColliderGroups;
|
||||
|
||||
private NativePoints _nativePoints;
|
||||
private NativePointer<BlittableRootBone> _rootBoneWrapper;
|
||||
|
||||
private readonly IList<NativeTransform> _transformWrappers = new List<NativeTransform>();
|
||||
private readonly IList<NativePointer<BlittablePoint>> _points = new List<NativePointer<BlittablePoint>>();
|
||||
|
||||
public FastSpringRootBone(
|
||||
TransformRegistry transformRegistry,
|
||||
Transform transform,
|
||||
RootBoneRegistry rootBoneRegistry,
|
||||
ColliderGroupRegistry colliderGroupRegistry
|
||||
)
|
||||
{
|
||||
_transformRegistry = transformRegistry;
|
||||
_transform = transform;
|
||||
_rootBoneRegistry = rootBoneRegistry;
|
||||
_colliderGroupRegistry = colliderGroupRegistry;
|
||||
}
|
||||
|
||||
public IReadOnlyList<FastSpringBoneColliderGroup> ColliderGroups
|
||||
{
|
||||
get => _nativeColliderGroups.ColliderGroups;
|
||||
set => _nativeColliderGroups.ColliderGroups = value;
|
||||
}
|
||||
|
||||
public unsafe void Initialize(
|
||||
float gravityPower,
|
||||
Vector3 gravityDir,
|
||||
float dragForce,
|
||||
float stiffnessForce,
|
||||
IReadOnlyList<FastSpringBoneColliderGroup> colliderGroups,
|
||||
float radius,
|
||||
Transform center)
|
||||
{
|
||||
_radius = radius;
|
||||
if (center != null)
|
||||
{
|
||||
_center = new NativeTransform(_transformRegistry, TransformSynchronizationType.PullOnly, center);
|
||||
}
|
||||
|
||||
_nativeColliderGroups = new NativeColliderGroups(colliderGroups);
|
||||
|
||||
NativeTransform parent = null;
|
||||
if (_transform.parent)
|
||||
{
|
||||
parent = new NativeTransform(_transformRegistry, TransformSynchronizationType.PullOnly, _transform.parent);
|
||||
}
|
||||
SetupRecursive(_transform, parent);
|
||||
|
||||
_nativePoints = new NativePoints(_points);
|
||||
|
||||
_rootBoneWrapper = new NativePointer<BlittableRootBone>(new BlittableRootBone(gravityPower, gravityDir, dragForce, stiffnessForce, _nativePoints.GetUnsafePtr()));
|
||||
_rootBoneRegistry.Register(_rootBoneWrapper);
|
||||
_colliderGroupRegistry.Register(_nativeColliderGroups);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_colliderGroupRegistry.Unregister(_nativeColliderGroups);
|
||||
_rootBoneRegistry.Unregister(_rootBoneWrapper);
|
||||
|
||||
foreach (var transformWrapper in _transformWrappers)
|
||||
{
|
||||
transformWrapper.Dispose();
|
||||
}
|
||||
|
||||
foreach (var point in _points)
|
||||
{
|
||||
point.Dispose();
|
||||
}
|
||||
|
||||
_center?.Dispose();
|
||||
_nativeColliderGroups?.Dispose();
|
||||
_nativePoints.Dispose();
|
||||
_rootBoneWrapper.Dispose();
|
||||
}
|
||||
|
||||
private unsafe void SetupRecursive(Transform trs, NativeTransform parent = null)
|
||||
{
|
||||
var transformWrapper = new NativeTransform(_transformRegistry, TransformSynchronizationType.PushOnly, trs, parent);
|
||||
_transformWrappers.Add(transformWrapper);
|
||||
|
||||
var point = new NativePointer<BlittablePoint>(
|
||||
new BlittablePoint(
|
||||
trs,
|
||||
_radius,
|
||||
_center != null ? _center.GetUnsafePtr() : null,
|
||||
_nativeColliderGroups.GetUnsafePtr(),
|
||||
transformWrapper.GetUnsafePtr())
|
||||
);
|
||||
_points.Add(point);
|
||||
|
||||
for (var i = 0; i < trs.childCount; ++i)
|
||||
{
|
||||
SetupRecursive(trs.GetChild(i), transformWrapper);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 24cdd60af2d54c908e84b17802bfb5bc
|
||||
timeCreated: 1550036996
|
||||
21
Assets/VRM/Runtime/FastSpringBone/FastSpringBone.asmdef
Normal file
21
Assets/VRM/Runtime/FastSpringBone/FastSpringBone.asmdef
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"name": "FastSpringBone",
|
||||
"references": [
|
||||
"GUID:2665a8d13d1b3f18800f46e256720795"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": true,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": false,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.unity.burst",
|
||||
"expression": "0.0.1",
|
||||
"define": "ENABLE_SPRINGBONE_BURST"
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ac229b552c3025545b074203f857547c
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/VRM/Runtime/FastSpringBone/NativeWrappers.meta
Normal file
8
Assets/VRM/Runtime/FastSpringBone/NativeWrappers.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 96634b0bb2d12d044a21f3fdff7a2c43
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
using Unity.Collections;
|
||||
using VRM.FastSpringBones.Blittables;
|
||||
|
||||
namespace VRM.FastSpringBones.NativeWrappers
|
||||
{
|
||||
/// <summary>
|
||||
/// BlittableColliderGroupのライフサイクルを管理するWrapper
|
||||
/// </summary>
|
||||
public sealed unsafe class NativeColliderGroup : IDisposable
|
||||
{
|
||||
private readonly NativePointer<BlittableColliderGroup> _nativePointer;
|
||||
|
||||
private NativeArray<BlittableCollider> Colliders { get; }
|
||||
|
||||
public BlittableColliderGroup* GetUnsafePtr() => _nativePointer.GetUnsafePtr();
|
||||
|
||||
public NativeColliderGroup(BlittableCollider[] colliders, NativeTransform nativeTransform)
|
||||
{
|
||||
Colliders = new NativeArray<BlittableCollider>(colliders, Allocator.Persistent);
|
||||
_nativePointer = new NativePointer<BlittableColliderGroup>(new BlittableColliderGroup(Colliders, nativeTransform.GetUnsafePtr()));
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (Colliders.IsCreated) Colliders.Dispose();
|
||||
|
||||
_nativePointer.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4cf2baba01384c31a1fdcca7489007f4
|
||||
timeCreated: 1550640666
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Unity.Collections;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
using VRM.FastSpringBones.Blittables;
|
||||
using VRM.FastSpringBones.Components;
|
||||
|
||||
namespace VRM.FastSpringBones.NativeWrappers
|
||||
{
|
||||
/// <summary>
|
||||
/// BlittableColliderGroupsのライフサイクルを管理するWrapper
|
||||
/// </summary>
|
||||
public sealed unsafe class NativeColliderGroups : IDisposable
|
||||
{
|
||||
private readonly NativePointer<BlittableColliderGroups> _nativePointer = new NativePointer<BlittableColliderGroups>();
|
||||
private NativeArray<BlittableColliderGroup> _colliderGroupArray;
|
||||
private IReadOnlyList<FastSpringBoneColliderGroup> _colliderGroups;
|
||||
|
||||
//Disposeされた後にUpdateColliderGroupsが呼ばれるのを防ぐためのフラグ
|
||||
private bool _isDisposed;
|
||||
|
||||
public BlittableColliderGroups* GetUnsafePtr() => _nativePointer.GetUnsafePtr();
|
||||
public void DrawGizmos() => _nativePointer.Value.DrawGizmos();
|
||||
|
||||
public IReadOnlyList<FastSpringBoneColliderGroup> ColliderGroups
|
||||
{
|
||||
get => _colliderGroups;
|
||||
set
|
||||
{
|
||||
_colliderGroups = value;
|
||||
UpdateColliderGroups();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateColliderGroups()
|
||||
{
|
||||
if (_isDisposed) return;
|
||||
if (_colliderGroupArray.IsCreated)
|
||||
{
|
||||
_colliderGroupArray.Dispose();
|
||||
}
|
||||
CreateColliderGroupArray(_colliderGroups);
|
||||
UpdateData();
|
||||
}
|
||||
|
||||
public NativeColliderGroups(IReadOnlyList<FastSpringBoneColliderGroup> colliderGroups)
|
||||
{
|
||||
_colliderGroups = colliderGroups;
|
||||
UpdateColliderGroups();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_colliderGroupArray.IsCreated)
|
||||
{
|
||||
_colliderGroupArray.Dispose();
|
||||
_isDisposed = true;
|
||||
}
|
||||
_nativePointer.Dispose();
|
||||
}
|
||||
|
||||
private void CreateColliderGroupArray(IReadOnlyList<FastSpringBoneColliderGroup> colliderGroups)
|
||||
{
|
||||
_colliderGroupArray = new NativeArray<BlittableColliderGroup>(colliderGroups.Count, Allocator.Persistent);
|
||||
for (var i = 0; i < _colliderGroupArray.Length; ++i)
|
||||
{
|
||||
_colliderGroupArray[i] = *colliderGroups[i].ColliderGroupPtr;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateData()
|
||||
{
|
||||
_nativePointer.Value = new BlittableColliderGroups(
|
||||
(BlittableColliderGroup*)_colliderGroupArray.GetUnsafePtr(),
|
||||
_colliderGroupArray.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3944dc9ee4a94814bc1d333fd0b7ba82
|
||||
timeCreated: 1550645184
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
using System;
|
||||
using Unity.Collections;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
|
||||
namespace VRM.FastSpringBones.NativeWrappers
|
||||
{
|
||||
public sealed class NativePointer<T> : IDisposable where T : unmanaged
|
||||
{
|
||||
private readonly unsafe T* _unsafePtr;
|
||||
|
||||
public unsafe T* GetUnsafePtr() => _unsafePtr;
|
||||
|
||||
public unsafe T Value
|
||||
{
|
||||
get => *_unsafePtr;
|
||||
set => *_unsafePtr = value;
|
||||
}
|
||||
|
||||
public unsafe NativePointer()
|
||||
{
|
||||
_unsafePtr = (T*)UnsafeUtility.Malloc(sizeof(T), 16, Allocator.Persistent);
|
||||
}
|
||||
|
||||
public unsafe NativePointer(T value)
|
||||
{
|
||||
_unsafePtr = (T*)UnsafeUtility.Malloc(sizeof(T), 16, Allocator.Persistent);
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public unsafe void Dispose()
|
||||
{
|
||||
UnsafeUtility.Free(_unsafePtr, Allocator.Persistent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 70f8b67ae2644eb999cfb45ea5bf25a3
|
||||
timeCreated: 1595316733
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Unity.Collections;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
using VRM.FastSpringBones.Blittables;
|
||||
|
||||
namespace VRM.FastSpringBones.NativeWrappers
|
||||
{
|
||||
/// <summary>
|
||||
/// BlittablePointsGroupのライフサイクルを管理するWrapper
|
||||
/// </summary>
|
||||
public sealed unsafe class NativePoints : IDisposable
|
||||
{
|
||||
private readonly NativePointer<BlittablePoints> _nativePointer;
|
||||
private NativeArray<BlittablePoint> _buffer;
|
||||
|
||||
public BlittablePoints* GetUnsafePtr() => _nativePointer.GetUnsafePtr();
|
||||
|
||||
public NativePoints(IList<NativePointer<BlittablePoint>> points)
|
||||
{
|
||||
_buffer = new NativeArray<BlittablePoint>(points.Count, Allocator.Persistent);
|
||||
for (var i = 0; i < _buffer.Length; ++i)
|
||||
{
|
||||
_buffer[i] = points[i].Value;
|
||||
}
|
||||
|
||||
_nativePointer = new NativePointer<BlittablePoints>(new BlittablePoints((BlittablePoint*) _buffer.GetUnsafePtr(), _buffer.Length));
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_buffer.IsCreated)
|
||||
{
|
||||
_buffer.Dispose();
|
||||
}
|
||||
_nativePointer.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7a8763ad7e8243d3b4001a2beb37bf9d
|
||||
timeCreated: 1550723674
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using VRM.FastSpringBones.Blittables;
|
||||
using VRM.FastSpringBones.Registries;
|
||||
|
||||
namespace VRM.FastSpringBones.NativeWrappers
|
||||
{
|
||||
/// <summary>
|
||||
/// BlittableTransformのライフサイクルを管理するWrapper
|
||||
/// </summary>
|
||||
public sealed class NativeTransform : IDisposable
|
||||
{
|
||||
private readonly NativePointer<BlittableTransform> _nativePointer;
|
||||
public Transform Transform { get; }
|
||||
|
||||
private readonly TransformRegistry _transformRegistry;
|
||||
|
||||
public unsafe BlittableTransform* GetUnsafePtr() => _nativePointer.GetUnsafePtr();
|
||||
public BlittableTransform Value => _nativePointer.Value;
|
||||
|
||||
public unsafe NativeTransform(
|
||||
TransformRegistry transformRegistry,
|
||||
TransformSynchronizationType transformSynchronizationType,
|
||||
Transform transform,
|
||||
NativeTransform parent = null
|
||||
)
|
||||
{
|
||||
_nativePointer = new NativePointer<BlittableTransform>(new BlittableTransform(parent != null ? parent.GetUnsafePtr() : null, transform));
|
||||
|
||||
Transform = transform;
|
||||
|
||||
_transformRegistry = transformRegistry;
|
||||
_transformRegistry.Register(this, transformSynchronizationType);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_transformRegistry.Unregister(this);
|
||||
|
||||
_nativePointer.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2acc8862ffb44f4fbd4e1e03e9a9d46e
|
||||
timeCreated: 1550545201
|
||||
8
Assets/VRM/Runtime/FastSpringBone/Registries.meta
Normal file
8
Assets/VRM/Runtime/FastSpringBone/Registries.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: daa8d50bee84b0c4387d22784cce66ff
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
using VRM.FastSpringBones.NativeWrappers;
|
||||
|
||||
namespace VRM.FastSpringBones.Registries
|
||||
{
|
||||
public sealed class ColliderGroupRegistry : Registry<NativeColliderGroups>
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: eec0fe3cd3694a379885fa62a9994bd5
|
||||
timeCreated: 1594963749
|
||||
28
Assets/VRM/Runtime/FastSpringBone/Registries/Registry.cs
Normal file
28
Assets/VRM/Runtime/FastSpringBone/Registries/Registry.cs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace VRM.FastSpringBones.Registries
|
||||
{
|
||||
public class Registry<T>
|
||||
{
|
||||
private readonly List<T> _items = new List<T>();
|
||||
private Action _onValueChanged;
|
||||
|
||||
public IReadOnlyList<T> Items => _items;
|
||||
|
||||
public void Register(T value)
|
||||
{
|
||||
_items.Add(value);
|
||||
_onValueChanged?.Invoke();
|
||||
}
|
||||
|
||||
public void Unregister(T value)
|
||||
{
|
||||
_items.Remove(value);
|
||||
_onValueChanged?.Invoke();
|
||||
}
|
||||
|
||||
public void SubscribeOnValueChanged(Action action) => _onValueChanged += action;
|
||||
public void UnSubscribeOnValueChanged(Action action) => _onValueChanged -= action;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0d3b558d03dd42b184512fe19797ff07
|
||||
timeCreated: 1595407071
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
using VRM.FastSpringBones.Blittables;
|
||||
using VRM.FastSpringBones.NativeWrappers;
|
||||
|
||||
namespace VRM.FastSpringBones.Registries
|
||||
{
|
||||
/// <summary>
|
||||
/// 今生きているRootBoneの一覧を返すクラス
|
||||
/// </summary>
|
||||
public sealed class RootBoneRegistry : Registry<NativePointer<BlittableRootBone>>
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4609c8e2a4c64fb7b3bfa587f475e965
|
||||
timeCreated: 1550734399
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using VRM.FastSpringBones.NativeWrappers;
|
||||
|
||||
namespace VRM.FastSpringBones.Registries
|
||||
{
|
||||
/// <summary>
|
||||
/// 今生きているTransformの一覧を返すクラス
|
||||
/// </summary>
|
||||
public sealed class TransformRegistry
|
||||
{
|
||||
private readonly List<NativeTransform> _transforms = new List<NativeTransform>();
|
||||
public IReadOnlyList<NativeTransform> Transforms => _transforms;
|
||||
|
||||
private readonly List<NativeTransform> _pullTargets = new List<NativeTransform>();
|
||||
public IReadOnlyList<NativeTransform> PullTargets => _pullTargets;
|
||||
|
||||
private readonly List<NativeTransform> _pushTargets = new List<NativeTransform>();
|
||||
public IReadOnlyList<NativeTransform> PushTargets => _pushTargets;
|
||||
|
||||
private Action _onValueChanged;
|
||||
|
||||
public void SubscribeOnValueChanged(Action action) => _onValueChanged += action;
|
||||
|
||||
public void UnSubscribeOnValueChanged(Action action) => _onValueChanged -= action;
|
||||
|
||||
public void Register(NativeTransform nativeTransform, TransformSynchronizationType synchronizationType)
|
||||
{
|
||||
_transforms.Add(nativeTransform);
|
||||
switch (synchronizationType)
|
||||
{
|
||||
case TransformSynchronizationType.PullOnly:
|
||||
_pullTargets.Add(nativeTransform);
|
||||
break;
|
||||
case TransformSynchronizationType.PushOnly:
|
||||
_pushTargets.Add(nativeTransform);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(synchronizationType), synchronizationType, null);
|
||||
}
|
||||
_onValueChanged?.Invoke();
|
||||
}
|
||||
|
||||
public void Unregister(NativeTransform nativeTransform)
|
||||
{
|
||||
_transforms.Remove(nativeTransform);
|
||||
|
||||
if (_pullTargets.Contains(nativeTransform))
|
||||
{
|
||||
_pullTargets.Remove(nativeTransform);
|
||||
}
|
||||
|
||||
if (_pushTargets.Contains(nativeTransform))
|
||||
{
|
||||
_pushTargets.Remove(nativeTransform);
|
||||
}
|
||||
_onValueChanged?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 102dd7059fb34c00a7d1d6d4f2c38729
|
||||
timeCreated: 1550666913
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
namespace VRM.FastSpringBones.Registries
|
||||
{
|
||||
public enum TransformSynchronizationType
|
||||
{
|
||||
PullOnly,
|
||||
PushOnly,
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6d3911eb7ee54861b51bccf4ed32aec2
|
||||
timeCreated: 1551169872
|
||||
8
Assets/VRM/Runtime/FastSpringBone/Schedulers.meta
Normal file
8
Assets/VRM/Runtime/FastSpringBone/Schedulers.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 802ad91bcfdacbd4bbce16eff061cd68
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
#if ENABLE_SPRINGBONE_BURST
|
||||
using Unity.Burst;
|
||||
#endif
|
||||
using Unity.Collections;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
using Unity.Jobs;
|
||||
using UnityEngine.Jobs;
|
||||
using UnityEngine.Profiling;
|
||||
using VRM.FastSpringBones.Blittables;
|
||||
using VRM.FastSpringBones.NativeWrappers;
|
||||
using VRM.FastSpringBones.Registries;
|
||||
|
||||
namespace VRM.FastSpringBones.Schedulers
|
||||
{
|
||||
/// <summary>
|
||||
/// GameObjectの世界からBlittableな世界へTransformを複製する処理を行うクラス
|
||||
/// </summary>
|
||||
public sealed unsafe class PullTransformJobScheduler : IDisposable
|
||||
{
|
||||
private BlittableTransform** _transformPointers;
|
||||
private TransformAccessArray _transformAccessArray;
|
||||
|
||||
private readonly CustomSampler _sampler = CustomSampler.Create("Schedule CopyFromTransformJob");
|
||||
private readonly TransformRegistry _transformRegistry;
|
||||
|
||||
private bool _dirty = true;
|
||||
|
||||
private IReadOnlyList<NativeTransform> Targets => _transformRegistry.PullTargets;
|
||||
|
||||
public PullTransformJobScheduler(TransformRegistry transformRegistry)
|
||||
{
|
||||
_transformRegistry = transformRegistry;
|
||||
|
||||
_transformRegistry.SubscribeOnValueChanged(OnTransformChanged);
|
||||
}
|
||||
|
||||
private void OnTransformChanged()
|
||||
{
|
||||
_dirty = true;
|
||||
}
|
||||
|
||||
public JobHandle Schedule(JobHandle dependOn = default(JobHandle))
|
||||
{
|
||||
if (Targets.Count == 0)
|
||||
{
|
||||
return dependOn;
|
||||
}
|
||||
|
||||
_sampler.Begin();
|
||||
|
||||
// リストが変更されていたらバッファを再構築
|
||||
if (_dirty)
|
||||
{
|
||||
ReconstructBuffers();
|
||||
|
||||
_dirty = false;
|
||||
}
|
||||
|
||||
// ジョブを発火
|
||||
var job = new Job { TransformPointers = _transformPointers };
|
||||
var jobHandle = job.Schedule(_transformAccessArray, dependOn);
|
||||
|
||||
_sampler.End();
|
||||
|
||||
return jobHandle;
|
||||
}
|
||||
|
||||
private void ReconstructBuffers()
|
||||
{
|
||||
ReleaseBuffers();
|
||||
|
||||
var transforms = Targets;
|
||||
_transformPointers = (BlittableTransform**)UnsafeUtility.Malloc(
|
||||
sizeof(BlittableTransform*) * transforms.Count,
|
||||
16,
|
||||
Allocator.Persistent
|
||||
);
|
||||
|
||||
_transformAccessArray = new TransformAccessArray(transforms.Count);
|
||||
|
||||
for (var i = 0; i < transforms.Count; i++)
|
||||
{
|
||||
_transformPointers[i] = transforms[i].GetUnsafePtr();
|
||||
_transformAccessArray.Add(transforms[i].Transform);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ReleaseBuffers();
|
||||
_transformRegistry.UnSubscribeOnValueChanged(OnTransformChanged);
|
||||
}
|
||||
|
||||
private void ReleaseBuffers()
|
||||
{
|
||||
if (_transformAccessArray.isCreated) _transformAccessArray.Dispose();
|
||||
if (_transformPointers != null)
|
||||
{
|
||||
UnsafeUtility.Free(_transformPointers, Allocator.Persistent);
|
||||
_transformPointers = null;
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_SPRINGBONE_BURST
|
||||
[BurstCompile]
|
||||
#endif
|
||||
private struct Job : IJobParallelForTransform
|
||||
{
|
||||
[NativeDisableUnsafePtrRestriction] public BlittableTransform** TransformPointers;
|
||||
|
||||
public void Execute(int index, TransformAccess transform)
|
||||
{
|
||||
TransformPointers[index]->PullFrom(transform);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 83ca6a73284247c0a809eb9b83b6296b
|
||||
timeCreated: 1550547066
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
#if ENABLE_SPRINGBONE_BURST
|
||||
using Unity.Burst;
|
||||
#endif
|
||||
using Unity.Collections;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
using Unity.Jobs;
|
||||
using UnityEngine.Jobs;
|
||||
using UnityEngine.Profiling;
|
||||
using VRM.FastSpringBones.Blittables;
|
||||
using VRM.FastSpringBones.NativeWrappers;
|
||||
using VRM.FastSpringBones.Registries;
|
||||
|
||||
namespace VRM.FastSpringBones.Schedulers
|
||||
{
|
||||
/// <summary>
|
||||
/// Blittableな世界からGameObjectの世界へTransformを送り込む処理を行うクラス
|
||||
/// </summary>
|
||||
public sealed unsafe class PushTransformJobScheduler : IDisposable
|
||||
{
|
||||
private BlittableTransform** _transformPointers;
|
||||
private TransformAccessArray _transformAccessArray;
|
||||
|
||||
private readonly CustomSampler _sampler = CustomSampler.Create("Schedule CopyFromTransformJob");
|
||||
private readonly TransformRegistry _transformRegistry;
|
||||
|
||||
private bool _dirty = true;
|
||||
|
||||
private IReadOnlyList<NativeTransform> Targets => _transformRegistry.PushTargets;
|
||||
|
||||
public PushTransformJobScheduler(TransformRegistry transformRegistry)
|
||||
{
|
||||
_transformRegistry = transformRegistry;
|
||||
|
||||
_transformRegistry.SubscribeOnValueChanged(OnTransformChanged);
|
||||
}
|
||||
|
||||
private void OnTransformChanged()
|
||||
{
|
||||
_dirty = true;
|
||||
}
|
||||
|
||||
public JobHandle Schedule(JobHandle dependOn = default(JobHandle))
|
||||
{
|
||||
if (Targets.Count == 0)
|
||||
{
|
||||
return dependOn;
|
||||
}
|
||||
|
||||
_sampler.Begin();
|
||||
|
||||
// リストが変更されていたらバッファを再構築
|
||||
if (_dirty)
|
||||
{
|
||||
ReconstructBuffers();
|
||||
|
||||
_dirty = false;
|
||||
}
|
||||
|
||||
// Jobを発火
|
||||
var job = new Job { TransformPointers = _transformPointers };
|
||||
var jobHandle = job.Schedule(_transformAccessArray, dependOn);
|
||||
|
||||
_sampler.End();
|
||||
|
||||
return jobHandle;
|
||||
}
|
||||
|
||||
private void ReconstructBuffers()
|
||||
{
|
||||
ReleaseBuffers();
|
||||
|
||||
var transforms = Targets;
|
||||
_transformPointers = (BlittableTransform**)UnsafeUtility.Malloc(
|
||||
sizeof(BlittableTransform*) * transforms.Count,
|
||||
16,
|
||||
Allocator.Persistent
|
||||
);
|
||||
|
||||
_transformAccessArray = new TransformAccessArray(transforms.Count);
|
||||
|
||||
for (var i = 0; i < transforms.Count; i++)
|
||||
{
|
||||
_transformPointers[i] = transforms[i].GetUnsafePtr();
|
||||
_transformAccessArray.Add(transforms[i].Transform);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ReleaseBuffers();
|
||||
_transformRegistry.UnSubscribeOnValueChanged(OnTransformChanged);
|
||||
}
|
||||
|
||||
private void ReleaseBuffers()
|
||||
{
|
||||
if (_transformAccessArray.isCreated) _transformAccessArray.Dispose();
|
||||
if (_transformPointers != null)
|
||||
{
|
||||
UnsafeUtility.Free(_transformPointers, Allocator.Persistent);
|
||||
_transformPointers = null;
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_SPRINGBONE_BURST
|
||||
[BurstCompile]
|
||||
#endif
|
||||
private struct Job : IJobParallelForTransform
|
||||
{
|
||||
[NativeDisableUnsafePtrRestriction] public BlittableTransform** TransformPointers;
|
||||
|
||||
public void Execute(int index, TransformAccess transform)
|
||||
{
|
||||
TransformPointers[index]->PushTo(transform);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5a12fcea984d4387a5f3d0f5291df34e
|
||||
timeCreated: 1550717407
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
#if ENABLE_SPRINGBONE_BURST
|
||||
using Unity.Burst;
|
||||
#endif
|
||||
using Unity.Collections;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
using Unity.Jobs;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Profiling;
|
||||
using VRM.FastSpringBones.Blittables;
|
||||
using VRM.FastSpringBones.NativeWrappers;
|
||||
using VRM.FastSpringBones.Registries;
|
||||
|
||||
namespace VRM.FastSpringBones.Schedulers
|
||||
{
|
||||
/// <summary>
|
||||
/// SpringBoneを更新する処理を行うクラス
|
||||
/// </summary>
|
||||
public sealed unsafe class UpdateSpringBoneJobScheduler : IDisposable
|
||||
{
|
||||
private BlittableRootBone** _rootBonePointers;
|
||||
|
||||
private readonly RootBoneRegistry _rootBoneRegistry;
|
||||
private readonly CustomSampler _sampler = CustomSampler.Create("Schedule CopyFromTransformJob");
|
||||
|
||||
private bool _dirty = true;
|
||||
|
||||
private IReadOnlyList<NativePointer<BlittableRootBone>> Targets => _rootBoneRegistry.Items;
|
||||
|
||||
public UpdateSpringBoneJobScheduler(RootBoneRegistry rootBoneRegistry)
|
||||
{
|
||||
_rootBoneRegistry = rootBoneRegistry;
|
||||
|
||||
_rootBoneRegistry.SubscribeOnValueChanged(OnRootBoneChanged);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ReleaseBuffer();
|
||||
_rootBoneRegistry.UnSubscribeOnValueChanged(OnRootBoneChanged);
|
||||
}
|
||||
|
||||
private void OnRootBoneChanged()
|
||||
{
|
||||
_dirty = true;
|
||||
}
|
||||
|
||||
public JobHandle Schedule(JobHandle dependOn = default(JobHandle))
|
||||
{
|
||||
if (Targets.Count == 0)
|
||||
{
|
||||
return dependOn;
|
||||
}
|
||||
|
||||
_sampler.Begin();
|
||||
|
||||
// リストが変更されていたらバッファを再構築
|
||||
if (_dirty)
|
||||
{
|
||||
ReconstructBuffers();
|
||||
|
||||
_dirty = false;
|
||||
}
|
||||
|
||||
// Jobを発火
|
||||
var job = new Job { RootBonePointers = _rootBonePointers, DeltaTime = Time.deltaTime };
|
||||
var jobHandle = job.Schedule(Targets.Count, 0, dependOn);
|
||||
|
||||
_sampler.End();
|
||||
|
||||
return jobHandle;
|
||||
}
|
||||
|
||||
private void ReconstructBuffers()
|
||||
{
|
||||
ReleaseBuffer();
|
||||
|
||||
_rootBonePointers = (BlittableRootBone**)UnsafeUtility.Malloc(
|
||||
sizeof(BlittableTransform*) * Targets.Count,
|
||||
16,
|
||||
Allocator.Persistent
|
||||
);
|
||||
|
||||
for (var i = 0; i < Targets.Count; i++)
|
||||
{
|
||||
_rootBonePointers[i] = Targets[i].GetUnsafePtr();
|
||||
}
|
||||
}
|
||||
|
||||
private void ReleaseBuffer()
|
||||
{
|
||||
if (_rootBonePointers == null) return;
|
||||
UnsafeUtility.Free(_rootBonePointers, Allocator.Persistent);
|
||||
_rootBonePointers = null;
|
||||
}
|
||||
|
||||
#if ENABLE_SPRINGBONE_BURST
|
||||
[BurstCompile]
|
||||
#endif
|
||||
private struct Job : IJobParallelFor
|
||||
{
|
||||
[NativeDisableUnsafePtrRestriction] public BlittableRootBone** RootBonePointers;
|
||||
public float DeltaTime;
|
||||
|
||||
public void Execute(int index)
|
||||
{
|
||||
// 各点を更新する
|
||||
RootBonePointers[index]->Update(DeltaTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a6b730c674ce4484862ddee8459c8598
|
||||
timeCreated: 1549516763
|
||||
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": [],
|
||||
|
|
|
|||
|
|
@ -867,8 +867,11 @@ RectTransform:
|
|||
- {fileID: 597950322}
|
||||
- {fileID: 935566651}
|
||||
- {fileID: 634488421}
|
||||
- {fileID: 1923377807}
|
||||
- {fileID: 630871733}
|
||||
- {fileID: 1365661828}
|
||||
- {fileID: 1329594714}
|
||||
- {fileID: 1391337186}
|
||||
- {fileID: 1923377807}
|
||||
m_Father: {fileID: 124675794}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
|
|
@ -1426,7 +1429,7 @@ RectTransform:
|
|||
- {fileID: 1736108988}
|
||||
- {fileID: 13043734}
|
||||
m_Father: {fileID: 339774397}
|
||||
m_RootOrder: 11
|
||||
m_RootOrder: 10
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
|
|
@ -1682,6 +1685,84 @@ MonoBehaviour:
|
|||
m_ChildControlHeight: 0
|
||||
m_ChildScaleWidth: 0
|
||||
m_ChildScaleHeight: 0
|
||||
--- !u!1 &668840864
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 668840865}
|
||||
- component: {fileID: 668840867}
|
||||
- component: {fileID: 668840866}
|
||||
m_Layer: 5
|
||||
m_Name: Label
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &668840865
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 668840864}
|
||||
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_Children: []
|
||||
m_Father: {fileID: 1391337186}
|
||||
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 &668840866
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 668840864}
|
||||
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_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: Use FastSpringBone
|
||||
--- !u!222 &668840867
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 668840864}
|
||||
m_CullTransparentMesh: 0
|
||||
--- !u!1 &773923918
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
|
@ -2325,9 +2406,7 @@ MonoBehaviour:
|
|||
m_HorizontalOverflow: 0
|
||||
m_VerticalOverflow: 0
|
||||
m_LineSpacing: 1
|
||||
m_Text: 'ResetSpringBone
|
||||
|
||||
'
|
||||
m_Text: ResetSpringBone
|
||||
--- !u!222 &919548010
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
|
|
@ -3360,6 +3439,80 @@ CanvasRenderer:
|
|||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1140410863}
|
||||
m_CullTransparentMesh: 0
|
||||
--- !u!1 &1160967486
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1160967487}
|
||||
- component: {fileID: 1160967489}
|
||||
- component: {fileID: 1160967488}
|
||||
m_Layer: 5
|
||||
m_Name: Checkmark
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &1160967487
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1160967486}
|
||||
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_Children: []
|
||||
m_Father: {fileID: 1808134149}
|
||||
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 &1160967488
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1160967486}
|
||||
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_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 &1160967489
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1160967486}
|
||||
m_CullTransparentMesh: 0
|
||||
--- !u!1 &1166391798
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
|
@ -4142,6 +4295,247 @@ CanvasRenderer:
|
|||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1322834809}
|
||||
m_CullTransparentMesh: 0
|
||||
--- !u!1 &1329594713
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1329594714}
|
||||
- component: {fileID: 1329594716}
|
||||
- component: {fileID: 1329594715}
|
||||
m_Layer: 5
|
||||
m_Name: _SpringBone_
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &1329594714
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1329594713}
|
||||
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_Children: []
|
||||
m_Father: {fileID: 339774397}
|
||||
m_RootOrder: 12
|
||||
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 &1329594715
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1329594713}
|
||||
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_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: "\u30B9\u30D7\u30EA\u30F3\u30B0\u30DC\u30FC\u30F3"
|
||||
--- !u!222 &1329594716
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1329594713}
|
||||
m_CullTransparentMesh: 0
|
||||
--- !u!1 &1365661827
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1365661828}
|
||||
- component: {fileID: 1365661830}
|
||||
- component: {fileID: 1365661829}
|
||||
m_Layer: 5
|
||||
m_Name: '_ '
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &1365661828
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1365661827}
|
||||
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_Children: []
|
||||
m_Father: {fileID: 339774397}
|
||||
m_RootOrder: 11
|
||||
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 &1365661829
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1365661827}
|
||||
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_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:
|
||||
--- !u!222 &1365661830
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1365661827}
|
||||
m_CullTransparentMesh: 0
|
||||
--- !u!1 &1391337185
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1391337186}
|
||||
- component: {fileID: 1391337187}
|
||||
m_Layer: 5
|
||||
m_Name: UseFastSpringBone
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &1391337186
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1391337185}
|
||||
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_Children:
|
||||
- {fileID: 1808134149}
|
||||
- {fileID: 668840865}
|
||||
m_Father: {fileID: 339774397}
|
||||
m_RootOrder: 13
|
||||
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 &1391337187
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1391337185}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 9085046f02f69544eb97fd06b6048fe2, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Navigation:
|
||||
m_Mode: 3
|
||||
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: 1808134150}
|
||||
toggleTransition: 1
|
||||
graphic: {fileID: 1160967488}
|
||||
m_Group: {fileID: 0}
|
||||
onValueChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_IsOn: 1
|
||||
--- !u!1 &1476033060
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
|
@ -4981,6 +5375,7 @@ MonoBehaviour:
|
|||
m_enableLipSync: {fileID: 935566650}
|
||||
m_enableAutoBlink: {fileID: 634488422}
|
||||
m_useUrpMaterial: {fileID: 630871734}
|
||||
m_useFastSpringBone: {fileID: 1391337187}
|
||||
m_src: {fileID: 0}
|
||||
m_target: {fileID: 802105000}
|
||||
Root: {fileID: 124675793}
|
||||
|
|
@ -5090,6 +5485,81 @@ MonoBehaviour:
|
|||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_IsOn: 0
|
||||
--- !u!1 &1808134148
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1808134149}
|
||||
- component: {fileID: 1808134151}
|
||||
- component: {fileID: 1808134150}
|
||||
m_Layer: 5
|
||||
m_Name: Background
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &1808134149
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1808134148}
|
||||
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_Children:
|
||||
- {fileID: 1160967487}
|
||||
m_Father: {fileID: 1391337186}
|
||||
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 &1808134150
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1808134148}
|
||||
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_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 &1808134151
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1808134148}
|
||||
m_CullTransparentMesh: 0
|
||||
--- !u!1 &1866921957
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
|
@ -5354,7 +5824,7 @@ RectTransform:
|
|||
m_Children:
|
||||
- {fileID: 919548008}
|
||||
m_Father: {fileID: 339774397}
|
||||
m_RootOrder: 10
|
||||
m_RootOrder: 14
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@ namespace VRM.SimpleViewer
|
|||
|
||||
[SerializeField]
|
||||
Toggle m_useUrpMaterial = default;
|
||||
|
||||
[SerializeField]
|
||||
Toggle m_useFastSpringBone = default;
|
||||
#endregion
|
||||
|
||||
[SerializeField]
|
||||
|
|
@ -172,6 +175,7 @@ namespace VRM.SimpleViewer
|
|||
m_reset = buttons.First(x => x.name == "ResetSpringBone");
|
||||
|
||||
var toggles = GameObject.FindObjectsOfType<Toggle>();
|
||||
m_useFastSpringBone = toggles.First(x => x.name == "UseFastSpringBone");
|
||||
m_enableLipSync = toggles.First(x => x.name == "EnableLipSync");
|
||||
m_enableAutoBlink = toggles.First(x => x.name == "EnableAutoBlink");
|
||||
|
||||
|
|
@ -300,6 +304,8 @@ namespace VRM.SimpleViewer
|
|||
m_version.text = string.Format("VRMViewer {0}.{1}",
|
||||
VRMVersion.MAJOR, VRMVersion.MINOR);
|
||||
m_open.onClick.AddListener(OnOpenClicked);
|
||||
m_useFastSpringBone.onValueChanged.AddListener(OnUseFastSpringBoneValueChanged);
|
||||
OnUseFastSpringBoneValueChanged(m_useFastSpringBone.isOn);
|
||||
|
||||
m_reset.onClick.AddListener(() => m_loaded.OnResetClicked());
|
||||
|
||||
|
|
@ -381,6 +387,11 @@ namespace VRM.SimpleViewer
|
|||
}
|
||||
}
|
||||
|
||||
void OnUseFastSpringBoneValueChanged(bool flag)
|
||||
{
|
||||
m_reset.gameObject.SetActive(!flag);
|
||||
}
|
||||
|
||||
static IMaterialDescriptorGenerator GetGltfMaterialGenerator(bool useUrp)
|
||||
{
|
||||
if (useUrp)
|
||||
|
|
@ -467,6 +478,11 @@ namespace VRM.SimpleViewer
|
|||
m_loaded = null;
|
||||
}
|
||||
|
||||
if (m_useFastSpringBone.isOn)
|
||||
{
|
||||
FastSpringBoneReplacer.ReplaceAsync(instance.Root);
|
||||
}
|
||||
|
||||
instance.EnableUpdateWhenOffscreen();
|
||||
instance.ShowMeshes();
|
||||
|
||||
|
|
|
|||
8
Assets/VRM/Samples/SpringBone.meta
Normal file
8
Assets/VRM/Samples/SpringBone.meta
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3fc3f1af567d73f41a5172249769f047
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"com.unity.burst": "1.4.11",
|
||||
"com.unity.ide.rider": "1.2.1",
|
||||
"com.unity.ide.visualstudio": "2.0.11",
|
||||
"com.unity.ide.vscode": "1.2.3",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,14 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"com.unity.burst": {
|
||||
"version": "1.4.11",
|
||||
"depth": 0,
|
||||
"source": "registry",
|
||||
"dependencies": {
|
||||
"com.unity.mathematics": "1.2.1"
|
||||
},
|
||||
"url": "https://packages.unity.com"
|
||||
},
|
||||
"com.unity.ext.nunit": {
|
||||
"version": "1.0.6",
|
||||
"depth": 1,
|
||||
|
|
@ -32,6 +41,13 @@
|
|||
"dependencies": {},
|
||||
"url": "https://packages.unity.com"
|
||||
},
|
||||
"com.unity.mathematics": {
|
||||
"version": "1.2.1",
|
||||
"depth": 1,
|
||||
"source": "registry",
|
||||
"dependencies": {},
|
||||
"url": "https://packages.unity.com"
|
||||
},
|
||||
"com.unity.postprocessing": {
|
||||
"version": "3.1.1",
|
||||
"depth": 0,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user