Home Game Development unity – Routinely create capsule colliders from bones?

unity – Routinely create capsule colliders from bones?

0
unity – Routinely create capsule colliders from bones?

[ad_1]

I’ve tried to routinely generate capsule colliders from bones by briefly making a mesh collider and utilizing raycast to seek out the gap to it from the bone, however once I create the capsule collider there appears to be some rounding errors that makes them very huge for bones far down in hierarchy. I’m doing this to make fabric physics work.

Any ideas what is perhaps incorrect? I’ve tried to transform to from world and native area to the perfect of my information, so am questioning if the one resolution is to flatten the bone hierarchy.

Code instance (wants Editor Coroutines put in):

utilizing System.Collections;
utilizing System.Collections.Generic;
utilizing System.Globalization;
utilizing System.Linq;
utilizing UnityEditor;
utilizing UnityEngine;
utilizing Unity.EditorCoroutines.Editor;


public class AutomaticColliderFitting : ScriptableWizard
{
    [field: SerializeField]
    public SkinnedMeshRenderer SkinnedMeshRenderer { get; set; }

    [field: SerializeField]
    public Fabric[] Garments { get; set; }

    [MenuItem("Tools/Fit Colliders To Bones")]
    static void CreateWizard()
    {
        CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;
        CultureInfo.CurrentUICulture = CultureInfo.InvariantCulture;
        DisplayWizard<AutomaticColliderFitting>("Computerized Collider Becoming", "Match");
    }

    IEnumerator ProcessBones()
    {
        var queriesHitBackfaces = Physics.queriesHitBackfaces;

        Checklist<CapsuleCollider> colliders = new Checklist<CapsuleCollider>();

        var meshCollider = this.SkinnedMeshRenderer.rework.root.gameObject.AddComponent<MeshCollider>();
        attempt
        {
            Physics.queriesHitBackfaces = true;

            meshCollider.sharedMesh = this.SkinnedMeshRenderer.sharedMesh;

            var maxDistance = this.SkinnedMeshRenderer.bounds.dimension.magnitude;

            foreach(var bone on this.SkinnedMeshRenderer.bones)
            {
                if(bone == null) proceed;

                Checklist<Vector3> X = new Checklist<Vector3> { Vector3.left, Vector3.proper };
                Checklist<Vector3> Y = new Checklist<Vector3> { Vector3.up, Vector3.down };
                Checklist<Vector3> Z = new Checklist<Vector3> { Vector3.ahead, Vector3.again };

                var resultX = RayCast(meshCollider, maxDistance, bone, X).ToList();
                var resultY = RayCast(meshCollider, maxDistance, bone, Y).ToList();
                var resultZ = RayCast(meshCollider, maxDistance, bone, Z).ToList();

                var closestToBoneX = resultX.The place(x => x.hit.collider != null).Choose(x => (x.hit.distance, x)).DefaultIfEmpty().Min().x;
                var closestToBoneY = resultY.The place(x => x.hit.collider != null).Choose(x => (x.hit.distance, x)).DefaultIfEmpty().Min().x;
                var closestToBoneZ = resultZ.The place(x => x.hit.collider != null).Choose(x => (x.hit.distance, x)).DefaultIfEmpty().Min().x;

                var tentative = new Checklist<(Vector3 course, Ray ray, RaycastHit hit)> { closestToBoneX, closestToBoneY, closestToBoneZ }.The place(x => x.course != default).ToList();
                if(tentative.Rely < 2) { proceed; }

                var closest = tentative.Choose(x => (x.hit.distance, x)).Min().x;
                tentative.Take away(closest);
                var furthest = tentative.Choose(x => (x.hit.distance, x)).Max().x;


                var collider = Undo.AddComponent<CapsuleCollider>(bone.gameObject);
                collider.heart = Vector3.zero;
                collider.radius = collider.rework.InverseTransformPoint(closest.hit.level).magnitude;
                collider.top = collider.rework.InverseTransformPoint(furthest.hit.level).magnitude;
                if(furthest.course == Vector3.left || furthest.course == Vector3.proper) { collider.course = 0; }
                if(furthest.course == Vector3.up || furthest.course == Vector3.down) { collider.course = 1; }
                if(furthest.course == Vector3.ahead || furthest.course == Vector3.again) { collider.course = 2; }

                bool overlapped = Physics.ComputePenetration(
                    collider, collider.rework.place, collider.rework.rotation,
                    meshCollider, meshCollider.rework.place, meshCollider.rework.rotation,
                    out Vector3 course, out float distance
                );

                if(overlapped)
                {
                    Choice.objects = default;
                    Choice.activeObject = collider;
                    SceneView.lastActiveSceneView.LookAtDirect(collider.rework.place, SceneView.lastActiveSceneView.rotation);
                    SceneView.RepaintAll();
                    yield return null;

                    if(EditorUtility.DisplayDialog("CapsuleCollider overlaps MeshCollider.", "Motion for CapsuleCollider?", "Add", "Take away"))
                    {
                        colliders.Add(collider);
                    }
                    else
                    {
                        DestroyImmediate(collider);
                    }
                }
                else
                {
                    colliders.Add(collider);
                }
            }
        }
        lastly
        {
            DestroyImmediate(meshCollider);
            // Restore setting
            Physics.queriesHitBackfaces = queriesHitBackfaces;
        }

        if(this.Garments != null)
        {
            foreach(var fabric on this.Garments) 
            {
                fabric.capsuleColliders = colliders.ToArray();
            }
        }

        static IEnumerable<(Vector3 course, Ray ray, RaycastHit hit)> RayCast(MeshCollider meshCollider, float maxDistance, Rework bone, Checklist<Vector3> X)
        {
            foreach(var course in X)
            {
                var ray = new Ray(bone.place, bone.TransformDirection(course));
                meshCollider.Raycast(ray, out RaycastHit raycastHit, maxDistance);
                yield return (course, ray, raycastHit);
            }
        }
    }

    /// <abstract>
    /// Match
    /// </abstract>
    void OnWizardCreate()
    {
        Undo.RegisterCompleteObjectUndo(this.SkinnedMeshRenderer, "Computerized Collider Becoming");
        Debug.Log("Computerized Collider Becoming.", this.SkinnedMeshRenderer);

        co = EditorCoroutineUtility.StartCoroutineOwnerless(this.ProcessBones());
    }

    personal EditorCoroutine co;

    void OnWizardUpdate()
    {
        this.helpString = "Suits colliders to mesh.";
    }
}

Made a brilliant easy character with a Fundamental Human metarig in Blender:

Example
Example

As you’ll be able to see the capsule will get a extremely bizarre dimension and it will get tremendous huge.

I get equally unhealthy outcomes when measuring distance to closest vertex. Might want to attempt to measure distance to every triangle as properly.

[ad_2]

LEAVE A REPLY

Please enter your comment!
Please enter your name here