メインコンテンツまでスキップ

vrm-1.0 の SpringBone 実装

構成

Model

備考

vrm10Instance.SpringBoneにモデル側の情報が格納されています

System(シングルトン)

備考

FastSpringBoneService.Instance はシングルトンですべての VRM-1.0 モデルのスプリングをまとめて処理します

実行

Update

備考

FastSpringBoneService.LateUpdate

[DefaultExecutionOrder(11010)]
ヒント

Vrm10Instance より後ろです。

[DefaultExecutionOrder(11000)]
public class Vrm10Instance : MonoBehaviour

v0.106.0 手動更新

手動更新

開始前に処理を回して SpringBone を安定させるなど、毎フレームの更新ではない想定です。

  • FastSpringBoneService.UpdateTypes.Manual を追加
  • FastSpringBoneService.ManualUpdate を追加
// 管理している VRM-1.0 がすべて入っている
List<VRM10Instance> instances;

// setup
foreach(var instance in instances)
{
// SpringBone を手動にするために、
// VRM-1.0 本体も手動に変更している。
// VRM本体 => SpringBone という処理順を守る。
instance.UpdateType = UpdateTypes.None;
}
FastSpringBoneService.Instance.UpdateType = FastSpringBoneService.UpdateTypes.Manual;

// each frame
foreach(var instance in instances)
{
// SpringBone よりも先に VRM10Instance を更新
instance.Runtime.Process();
}
// 最後に FastSpringBoneService を更新
// すべての VRM-1.0 の SpringBone がまとめて処理されます。
FastSpringBoneService.Instance.ManualUpdate(time.deltaTime);

機能

v0.106.0 毎フレーム外力を加える

外力

ジャンプや風など、一時的な力の表現を想定した機能です。

VRM10Instance instance;

// each frame
// 既存の Gravity に加算されます
instance.Runtime.ExternalForce = new Vector3(0.1f, 0, 0);

MonoBehaviour詳細

Vrm10InstanceSpringBone Vrm10Instance.SpringBone

Spring

[SerializeField]
public List<Spring> Springs = new List<Spring>();

ColliderGroup

public List<VRM10SpringBoneColliderGroup> ColliderGroups = new List<VRM10SpringBoneColliderGroup>();

Collider

public List<VRM10SpringBoneCollider> Colliders = new List<VRM10SpringBoneCollider>();

Job詳細

FastSpringBoneScheduler.Schedule(entry point)

JobHandle Schedule(float deltaTime)
private void LateUpdate()
{
if (UpdateType == UpdateTypes.LateUpdate)
{
_fastSpringBoneScheduler.Schedule(Time.deltaTime).Complete();
}
}

job の構成

        public JobHandle Schedule(float deltaTime)
{
var handle = default(JobHandle);
handle = _bufferCombiner.ReconstructIfDirty(handle);
if (!_bufferCombiner.HasBuffer)
{
return handle;
}

handle = new PullTransformJob
{
Transforms = _bufferCombiner.Transforms
}.Schedule(_bufferCombiner.TransformAccessArray, handle);

handle = new UpdateFastSpringBoneJob
{
Colliders = _bufferCombiner.Colliders,
Joints = _bufferCombiner.Joints,
Logics = _bufferCombiner.Logics,
Springs = _bufferCombiner.Springs,
Transforms = _bufferCombiner.Transforms,
DeltaTime = deltaTime,
}.Schedule(_bufferCombiner.Springs.Length, 1, handle);

handle = new PushTransformJob
{
Transforms = _bufferCombiner.Transforms
}.Schedule(_bufferCombiner.TransformAccessArray, handle);

return handle;
}