Пример #1
0
    public void GenerateColliders(ColliderGenerationSettings settings = null)
    {
        if (settings == null)
        {
            settings = ColliderGenerationSettings;
        }

        foreach (var c in GeneratedColliders.ToArray())
        {
            if (c != null)
            {
                DestroyImmediate(c.gameObject);
            }
        }

        GeneratedColliders.Clear();

        if (PointsContainer.childCount < 2)
        {
            return;
        }

        for (int i = 0; i < PointsContainer.childCount - 1; i++)
        {
            var a   = PointsContainer.GetChild(i).position;
            var b   = PointsContainer.GetChild(i + 1).position;
            var col = CreateColliderBetweenPoints(settings, a, b);

            GeneratedColliders.Add(col);
        }
    }
Пример #2
0
    private IEnumerator GenerateSplinesColliders(ColliderGenerationSettings settings = null)
    {
        var original_rotation = grindSurface.transform.rotation;

        grindSurface.transform.rotation = Quaternion.identity;

        yield return(null);

        foreach (var s in grindSurface.Splines)
        {
            s.GenerateColliders(settings);
        }

        yield return(null);

        grindSurface.transform.rotation = original_rotation;
    }
Пример #3
0
    private Collider CreateColliderBetweenPoints(ColliderGenerationSettings settings, Vector3 pointA, Vector3 pointB)
    {
        var go = new GameObject("Grind Cols")
        {
            layer = LayerMask.NameToLayer("Grindable")
        };

        go.transform.position = Vector3.Lerp(pointA, pointB, .5f);
        go.transform.LookAt(pointA);
        go.transform.SetParent(ColliderContainer != null ? ColliderContainer : transform);
        go.tag = $"Grind_{SurfaceType}";

        var length = Vector3.Distance(pointA, pointB);

        if (settings.ColliderType == ColliderGenerationSettings.ColliderTypes.Capsule)
        {
            var cap = go.AddComponent <CapsuleCollider>();

            cap.direction = 2;
            cap.radius    = settings.Radius;
            cap.height    = length + 2f * settings.Radius;

            go.transform.localPosition += go.transform.InverseTransformVector(new Vector3(0, -settings.Radius, 0));
        }
        else
        {
            var box = go.AddComponent <BoxCollider>();

            box.size = new Vector3(settings.Width, settings.Depth, length);

            if (settings.IsEdge)
            {
                var inset_direction = GetInsetDirection(settings, go.transform);
                var inset_distance  = settings.Width / 2f;

                go.transform.localPosition += inset_direction * inset_distance;
                go.transform.localPosition += go.transform.InverseTransformVector(new Vector3(0, -(settings.Depth / 2f), 0));
            }
        }

        return(go.GetComponent <Collider>());
    }
Пример #4
0
    private Vector3 GetInsetDirection(ColliderGenerationSettings settings, Transform collider_transform)
    {
        var root = collider_transform.parent;

        if (root.parent != null && root.parent.GetComponent <GrindSurface>() != null)
        {
            root = root.parent;
        }

        if (settings.AutoDetectEdgeAlignment)
        {
            var ray = new Ray(collider_transform.position + collider_transform.right * settings.Width + root.up, -root.up);

            if (Physics.Raycast(ray, out var hit, Mathf.Infinity, settings.LayerMask) == false || hit.transform.IsChildOf(transform.parent))
            {
                return(collider_transform.right);
            }

            return(-collider_transform.right);
        }

        return(settings.FlipEdge ? -collider_transform.right : collider_transform.right);
    }
    public static void Generate(GrindSurface surface, ColliderGenerationSettings collider_generation_settings = null)
    {
        IEnumerator routine()
        {
            var original_rotation = surface.transform.rotation;

            surface.transform.rotation = Quaternion.identity;

            yield return(null);

            settings = collider_generation_settings;

            // build a list of vertexes from child objects that are valid potential grindable surfaces
            // do a set offset sphere checks to see if we have open space in any cardinal directions

            vertices.Clear();
            vertexScores.Clear();
            endPoints.Clear();
            blockedPoints.Clear();
            activeSplinePoints.Clear();

            foreach (var m in surface.GetComponentsInChildren <MeshFilter>())
            {
                for (int i = 0; i < m.sharedMesh.vertexCount; i++)
                {
                    if (vertices.Count > MaxVertices)
                    {
                        break;
                    }

                    if (IsValidPotentialVertex(surface.transform, m, i, out var w, out var score))
                    {
                        if (vertices.Contains(w) == false)
                        {
                            vertices.Add(w);
                            vertexScores.Add(score);
                        }
                    }
                }
            }

            vertices = vertices.OrderByDescending(v => vertexScores[vertices.IndexOf(v)]).ToList();

            Debug.Log($"Found {vertices.Count} potential valid vertices in child meshes.");

            // start a grind spline by picking a valid vertex
            // find the nearest valid vert and add that, repeat until there are no valid verts left

            var start         = vertices[0];
            var active_spline = CreateSpline(surface, start, collider_generation_settings);
            var current_point = start;
            var current_index = 0;

            vertices.RemoveAt(0);

            endPoints.Add(start);

            AddSplinePoint(active_spline, start);

            while (active_spline != null)
            {
                RefreshSearchList();

                // if ran out of verts to use, we're done

                if (searchList.Count == 0 || (searchList.Count == 1 && searchList[0] == current_point))
                {
                    break;
                }

                // find nearest vert for our next spline point

                var previous_point = current_index > 0 ? active_spline.PointsContainer.GetChild(current_index - 1) : null;

                if (TryGetNextValidPoint(surface, out var next_point, current_point, previous_point?.position))
                {
                    if (vertices.Contains(next_point))
                    {
                        vertices.Remove(next_point);
                    }

                    AddSplinePoint(active_spline, next_point);

                    current_point = next_point;
                    current_index++;
                }