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); } }
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; }
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>()); }
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++; }