/// <summary> /// 指定された<see cref="VRMSpringBoneColliderGroup"/>を基に<see cref="DynamicBoneCollider"/>を設定します。 /// </summary> /// <param name="colliderGroup"></param> /// <param name="bonesForCollisionWithOtherAvatar"></param> /// <returns>生成した<see cref="DynamicBoneCollider"/>のリスト。</returns> private static IEnumerable <MonoBehaviour> ConvertVRMSpringBoneColliderGroup( VRMSpringBoneColliderGroup colliderGroup ) { var bone = colliderGroup.gameObject; return(colliderGroup.Colliders.Select(collider => { var dynamicBoneCollider = bone.AddComponent(DynamicBoneColliderType); DynamicBoneColliderType.GetField("m_Center").SetValue(dynamicBoneCollider, collider.Offset); DynamicBoneColliderType.GetField("m_Radius").SetValue(dynamicBoneCollider, collider.Radius); return dynamicBoneCollider as MonoBehaviour; }).ToList()); }
/// <summary> /// 指定された<see cref="VRMSpringBoneColliderGroup"/>を基に<see cref="DynamicBoneCollider"/>を設定します。 /// </summary> /// <param name="colliderGroup"></param> /// <param name="bonesForCollisionWithOtherAvatar"></param> /// <returns>生成した<see cref="DynamicBoneCollider"/>のリスト。</returns> private static IEnumerable <dynamic> ConvertVRMSpringBoneColliderGroup( VRMSpringBoneColliderGroup colliderGroup ) { var bone = colliderGroup.gameObject; return(colliderGroup.Colliders.Select(collider => { dynamic dynamicBoneCollider = bone.AddComponent(DynamicBoneColliderType); dynamicBoneCollider.m_Center = collider.Offset; dynamicBoneCollider.m_Radius = collider.Radius; return dynamicBoneCollider; }).ToList()); }
/// <summary> /// VRMSpringBone、およびVRMSpringBoneColliderGroupをコピーします。 /// </summary> /// <param name="sourceSpringBone"></param> /// <param name="destination"></param> /// <param name="sourceSkeletonBones"></param> /// <param name="transformMapping"></param> /// <returns>更新された <c>transformMapping</c> を返します。</returns> private static IDictionary <Transform, Transform> CopySpringBone( VRMSpringBone sourceSpringBone, GameObject destination, Dictionary <HumanBodyBones, Transform> sourceSkeletonBones, IDictionary <Transform, Transform> transformMapping ) { var destinationSecondary = destination.transform.Find("secondary").gameObject; ComponentUtility.CopyComponent(sourceSpringBone); ComponentUtility.PasteComponentAsNew(destinationSecondary); var destinationSpringBone = destinationSecondary.GetComponents <VRMSpringBone>().Last(); if (destinationSpringBone.m_center) { destinationSpringBone.m_center = transformMapping.ContainsKey(destinationSpringBone.m_center) ? transformMapping[destinationSpringBone.m_center] : (transformMapping[destinationSpringBone.m_center] = BoneMapper.FindCorrespondingBone( sourceBone: destinationSpringBone.m_center, source: sourceSpringBone.transform.root.gameObject, destination, sourceSkeletonBones )); } for (var i = 0; i < destinationSpringBone.RootBones.Count; i++) { var sourceSpringBoneRoot = destinationSpringBone.RootBones[i]; destinationSpringBone.RootBones[i] = sourceSpringBoneRoot ? (transformMapping.ContainsKey(sourceSpringBoneRoot) ? transformMapping[sourceSpringBoneRoot] : (transformMapping[sourceSpringBoneRoot] = BoneMapper.FindCorrespondingBone( sourceBone: sourceSpringBoneRoot, source: sourceSpringBone.transform.root.gameObject, destination, sourceSkeletonBones ))) : null; } for (var i = 0; i < destinationSpringBone.ColliderGroups.Length; i++) { var sourceColliderGroup = destinationSpringBone.ColliderGroups[i]; var destinationColliderGroupTransform = sourceColliderGroup ? (transformMapping.ContainsKey(sourceColliderGroup.transform) ? transformMapping[sourceColliderGroup.transform] : (transformMapping[sourceColliderGroup.transform] = BoneMapper.FindCorrespondingBone( sourceBone: sourceColliderGroup.transform, source: sourceSpringBone.transform.root.gameObject, destination, sourceSkeletonBones ))) : null; VRMSpringBoneColliderGroup destinationColliderGroup = null; if (destinationColliderGroupTransform) { CopyVRMSpringBones.CopySpringBoneColliderGroups( sourceBone: sourceColliderGroup.transform, destinationBone: destinationColliderGroupTransform ); destinationColliderGroup = destinationColliderGroupTransform.GetComponent <VRMSpringBoneColliderGroup>(); } destinationSpringBone.ColliderGroups[i] = destinationColliderGroup; } return(transformMapping); }
/// <summary> /// 子孫の<see cref="DynamicBone"/>を基に<see cref="VRMSpringBone"/>を設定します。 /// </summary> /// <param name="instance"></param> /// <param name="swayingParametersConverter"></param> private static void SetSpringBones(GameObject instance, ParametersConverter swayingParametersConverter) { var boneInfo = new BoneInfo(instance.GetComponent <VRMMeta>()); var secondary = instance.transform.Find("secondary").gameObject; GameObject.DestroyImmediate(secondary.GetComponent <VRMSpringBone>()); foreach (var dynamicBones in instance.GetComponentsInChildren(DynamicBoneType) .Select((dynamic dynamicBone) => { var parameters = swayingParametersConverter(new DynamicBoneParameters() { Damping = dynamicBone.m_Damping, DampingDistrib = dynamicBone.m_DampingDistrib, Elasticity = dynamicBone.m_Elasticity, ElasticityDistrib = dynamicBone.m_ElasticityDistrib, Stiffness = dynamicBone.m_Stiffness, StiffnessDistrib = dynamicBone.m_StiffnessDistrib, Inert = dynamicBone.m_Inert, InertDistrib = dynamicBone.m_InertDistrib, }, boneInfo); var colliderGroups = new List <VRMSpringBoneColliderGroup>(); if (dynamicBone.m_Colliders != null) { foreach (var collider in dynamicBone.m_Colliders) { if (!collider.transform.IsChildOf(instance.transform)) { // ルート外の参照を除外 continue; } VRMSpringBoneColliderGroup colliderGroup = collider.GetComponent <VRMSpringBoneColliderGroup>(); if (colliderGroup == null || colliderGroups.Contains(colliderGroup)) { continue; } colliderGroups.Add(colliderGroup); } } Vector3 gravity = dynamicBone.m_Gravity; return(dynamicBone, parameters, colliderGroups, compare: string.Join("\n", new[] { parameters.StiffnessForce, gravity.x, gravity.y, gravity.z, parameters.DragForce, (float)dynamicBone.m_Radius, }.Select(parameter => parameter.ToString("F2")) .Concat(colliderGroups .Select(colliderGroup => colliderGroup.transform.RelativePathFrom(instance.transform))) )); }) .GroupBy(dynamicBones => dynamicBones.compare)) // 同一パラメータでグループ化 { var dynamicBone = dynamicBones.First(); var springBone = secondary.AddComponent <VRMSpringBone>(); springBone.m_stiffnessForce = dynamicBone.parameters.StiffnessForce; Vector3 gravity = dynamicBone.dynamicBone.m_Gravity; springBone.m_gravityPower = gravity.magnitude; springBone.m_gravityDir = gravity.normalized; springBone.m_dragForce = dynamicBone.parameters.DragForce; springBone.RootBones = dynamicBones.Select(db => (Transform)db.dynamicBone.m_Root) .Where(transform => transform != null) .Distinct() .ToList(); springBone.m_hitRadius = dynamicBone.dynamicBone.m_Radius; springBone.ColliderGroups = dynamicBone.colliderGroups.ToArray(); } }
// Convert from VRMSpringBoneCollider public static SerializableSpringBoneColliderGroup FromSpringBoneColliderGroup(VRMSpringBoneColliderGroup colliderGroup) { Debug.Log($"Convert SpringBoneColliderGroup to serializable: Root={colliderGroup.transform.name}"); var serializableCollider = new SerializableSpringBoneColliderGroup(); serializableCollider.AttachedTo = HierarchyPath.FromTransform(colliderGroup.transform); // Copy values if (colliderGroup.Colliders != null) { foreach (var collider in colliderGroup.Colliders) { serializableCollider.Colliders.Add(new SerializableSpringBoneCollider(collider.Offset, collider.Radius)); } } return(serializableCollider); }