private void Generate() { UOUtility.DestroyChildren(Generated); wayPoints.Clear(); float localSpacing = 0; Joint joint = null; for (int i = 0; i < segmentCount; i++) { var seg = UOUtility.Instantiate(segmentPrefab, Generated.transform); seg.transform.Translate(0, 0, localSpacing); var segRB = seg.GetComponent <Rigidbody>(); // we fix the first segment so that the rope won't fall if (i == 0) { firstSegment = seg; segRB.constraints = RigidbodyConstraints.FreezePosition; } // we attach the rigidbody to the joint of the previous segment if (joint != null) { joint.connectedBody = segRB; } joint = seg.GetComponent <Joint>(); // we save segments as way points for the spline deformation. wayPoints.Add(seg); localSpacing += segmentSpacing; } UOUtility.Destroy(joint); }
public void CreateMeshes() { var used = new List <GameObject>(); if (curveSpace) { int i = 0; foreach (var curve in spline.curves) { var go = FindOrCreate("segment " + i++ + " mesh"); go.GetComponent <MeshBender>().SetInterval(curve); go.GetComponent <MeshCollider>().enabled = generateCollider; used.Add(go); } } else { var go = FindOrCreate("segment 1 mesh"); go.GetComponent <MeshBender>().SetInterval(spline, 0); go.GetComponent <MeshCollider>().enabled = generateCollider; used.Add(go); } // we destroy the unused objects. This is classic pooling to recycle game objects. foreach (var go in generated.transform .Cast <Transform>() .Select(child => child.gameObject).Except(used)) { UOUtility.Destroy(go); } }
public void CreateMeshes() { List <GameObject> used = new List <GameObject>(); for (int i = 0; i < spline.GetCurves().Count; i++) { var curve = spline.GetCurves()[i]; foreach (var tm in segments[i].transformedMeshes) { if (tm.mesh == null) { // if there is no mesh specified for this segment, we ignore it. continue; } // we try to find a game object previously generated. this avoids destroying/creating // game objects at each update, wich is faster. var childName = "segment " + i + " mesh " + segments[i].transformedMeshes.IndexOf(tm); var childTransform = generated.transform.Find(childName); GameObject go; if (childTransform == null) { go = UOUtility.Create(childName, generated, typeof(MeshFilter), typeof(MeshRenderer), typeof(MeshBender), typeof(MeshCollider)); go.isStatic = true; } else { go = childTransform.gameObject; } go.GetComponent <MeshRenderer>().material = tm.material; go.GetComponent <MeshCollider>().material = tm.physicMaterial; // we update the data in the bender. It will decide itself if the bending must be recalculated. MeshBender mb = go.GetComponent <MeshBender>(); mb.Source = tm.mesh; mb.Curve = curve; mb.Translation = tm.translation; mb.Rotation = Quaternion.Euler(tm.rotation); mb.Scale = tm.scale; mb.ComputeIfNeeded(); used.Add(go); } } // finally, we destroy the unused objects foreach (var go in generated.transform .Cast <Transform>() .Select(child => child.gameObject).Except(used)) { UOUtility.Destroy(go); } }
public void CreateMeshes() { var used = new List <GameObject>(); if (curveSpace) { int i = 0; foreach (var curve in spline.curves) { if (collider) { i++; var coll = FindOrCreateCollider("segment " + i + " collider"); coll.GetComponent <MeshBender>().SetInterval(curve); used.Add(coll); var render = FindOrCreateRender("segment " + i + " collider", "segment " + i + " render"); render.GetComponent <MeshBender>().SetInterval(curve); render.transform.parent = coll.transform; used.Add(render); } else { var render = FindOrCreateRender("none", "segment " + i + " render"); render.GetComponent <MeshBender>().SetInterval(curve); used.Add(render); } } } else { if (collider) { var coll = FindOrCreateCollider("segment 1 collider"); coll.GetComponent <MeshBender>().SetInterval(spline, 0); used.Add(coll); var render = FindOrCreateRender("segment 1 collider", "segment 1 render"); render.GetComponent <MeshBender>().SetInterval(spline, 0); render.transform.parent = coll.transform; used.Add(render); } else { var render = FindOrCreateRender("none", "segment 1 render"); render.GetComponent <MeshBender>().SetInterval(spline, 0); used.Add(render); } } // we destroy the unused objects. This is classic pooling to recycle game objects. foreach (var go in generated.transform.Cast <Transform>().Select(child => child.gameObject).Except(used)) { UOUtility.Destroy(go); } }
public void CreateMeshes() { #if UNITY_EDITOR // we don't update if we are in prefab mode if (PrefabStageUtility.GetCurrentPrefabStage() != null) { return; } #endif var used = new List <GameObject>(); if (curveSpace) { int i = 0; foreach (var curve in spline.curves) { var go = FindOrCreate("segment " + i++ + " mesh"); go.GetComponent <MeshBender>().SetInterval(curve); go.GetComponent <MeshCollider>().enabled = generateCollider; used.Add(go); } } else { var go = FindOrCreate("segment 1 mesh"); go.GetComponent <MeshBender>().SetInterval(spline, 0); go.GetComponent <MeshCollider>().enabled = generateCollider; used.Add(go); } // we destroy the unused objects. This is classic pooling to recycle game objects. foreach (var go in generated.transform .Cast <Transform>() .Select(child => child.gameObject).Except(used).ToList()) { UOUtility.Destroy(go); } }
public void CreateMeshes() { for (int j = 0; j < numOfGeneratedMeshes; ++j) { Debug.Log("Regenerating mesh " + generated[j]); var used = new List <GameObject>(); if (curveSpace) { int i = 0; foreach (var curve in spline.curves) { //j = mesh number, e.g. 0 = render mesh, 1 = collision //i = segment of mesh Mesh mesh = null; Material mat = null; if (j == 0) { if (meshDataInternal[j].meshPrefabs[i].GetComponent <SplineMeshData>().renderMesh == null) { mesh = backupMesh; Debug.LogWarning("Can't find mesh - using backup"); } else { mesh = meshDataInternal[j].meshPrefabs[i].GetComponent <SplineMeshData>().renderMesh; } } else { if (meshDataInternal[j].meshPrefabs[i].GetComponent <SplineMeshData>().collisionMesh == null) { mesh = backupMesh; Debug.LogWarning("Can't find mesh - using backup"); } else { mesh = meshDataInternal[j].meshPrefabs[i].GetComponent <SplineMeshData>().collisionMesh; } } if (meshDataInternal[j].meshPrefabs[i].GetComponent <SplineMeshData>().material == null) { mat = backupMaterial; Debug.LogWarning("Can't find material - using backup"); } else { mat = meshDataInternal[j].meshPrefabs[i].GetComponent <SplineMeshData>().material; } var go = FindOrCreate("segment " + i++ + " mesh", mesh, mat, j); go.GetComponent <MeshBender>().SetInterval(curve); if (j == 0) { go.GetComponent <MeshCollider>().enabled = false; go.GetComponent <MeshRenderer>().enabled = true; } else { go.GetComponent <MeshCollider>().enabled = true; go.GetComponent <MeshRenderer>().enabled = false; } used.Add(go); } } else { var go = FindOrCreate("segment 1 mesh", backupMesh, backupMaterial, j); go.GetComponent <MeshBender>().SetInterval(spline, 0); go.GetComponent <MeshCollider>().enabled = true; go.GetComponent <MeshRenderer>().enabled = true; used.Add(go); } // we destroy the unused objects. This is classic pooling to recycle game objects. foreach (var go in generated[j].transform .Cast <Transform>() .Select(child => child.gameObject).Except(used)) { UOUtility.Destroy(go); } } }
private void CreateMeshes() { if (null == spline) { return; } string generatedName = "generated by " + GetType().Name; var generatedTranform = transform.Find(generatedName); generated = generatedTranform != null ? generatedTranform.gameObject : UOUtility.Create(generatedName, gameObject); generated.isStatic = false == updateInPlayMode; generated.layer = gameObject.layer; var generatedChildren = generated.transform.Cast <Transform>().ToList(); foreach (var child in generatedChildren) { if (null == child) { continue; } var meshCollider = child.GetComponent <MeshCollider>(); if (meshCollider) { meshCollider.enabled = false; } } List <MeshVertex> sourceVertices = new List <MeshVertex>(2 + Mathf.Max(0, slice - 1)); float x_start = offset - width / 2; float x_end = offset + width / 2; sourceVertices.Add(new MeshVertex(new Vector3(0, 0, x_start), Vector3.up, new Vector2(+textureOffsetScale.x, 0))); for (int step = 1; step < slice; ++step) { float t = (float)step / (float)slice; float x = Mathf.Lerp(x_start, x_end, t); sourceVertices.Add(new MeshVertex(new Vector3(0, 0, x), Vector3.up, new Vector2(t / textureOffsetScale.z + textureOffsetScale.x, 0))); } sourceVertices.Add(new MeshVertex(new Vector3(0, 0, x_end), Vector3.up, new Vector2(1 / textureOffsetScale.z + textureOffsetScale.x, 0))); if (Mathf.Approximately(sampleSpacing, 0) || sampleSpacing <= 0) { Debug.LogError("Not enough sampleSpcaing. (must be greater than zero)"); return; } int lineCount = 0; List <MeshVertex> bentVertices = new List <MeshVertex>(); for (float d = 0.0f; d <= spline.Length; d += sampleSpacing) { var sample = spline.GetSampleAtDistance(d); if (heightSync) { var sampleLocationWS = spline.transform.TransformPoint(sample.location); RaycastHit hitInfo; if (Physics.Raycast(sampleLocationWS + Vector3.up * heightSyncTraceRange, -Vector3.up, out hitInfo, heightSyncTraceRange * 2, heightSyncLayerMask)) { var newSampleLocation = spline.transform.InverseTransformPoint(hitInfo.point); sample = new CurveSample(newSampleLocation, sample.tangent, sample.up, sample.scale, sample.roll, sample.distanceInCurve, sample.timeInCurve, sample.curve); } } for (int i = 0; i < sourceVertices.Count; ++i) { var bentVertex = sample.GetBent(sourceVertices[i]); bentVertex.normal = sample.up; if (heightSync) { var bentWS = spline.transform.TransformPoint(bentVertex.position); RaycastHit hitInfo; if (Physics.Raycast(bentWS + Vector3.up * heightSyncTraceRange, -Vector3.up, out hitInfo, heightSyncTraceRange * 2, heightSyncLayerMask)) { bentVertex.position = spline.transform.InverseTransformPoint(hitInfo.point); if (heightNormalSync) { bentVertex.normal = spline.transform.InverseTransformDirection(hitInfo.normal); } } } bentVertex.uv.y = (d / width) / textureOffsetScale.w + textureOffsetScale.y; bentVertices.Add(bentVertex); } ++lineCount; } if (1 >= lineCount) { Debug.LogError("Not enough line length"); return; } List <Transform> newGeneratedTransform = new List <Transform>(); int baseIndex = 0; int lineVerticesCount = 2 + Mathf.Max(0, slice - 1); List <int> triangles = new List <int>((lineVerticesCount - 1) * (lineCount - 1) * 2); for (int i = 0; i < lineCount - 1; ++i) { int nextBaseIndex = baseIndex + lineVerticesCount; for (int v = 0; v < lineVerticesCount - 1; ++v) { int[] vertices = new int[] { baseIndex + v, baseIndex + v + 1, nextBaseIndex + v, nextBaseIndex + v + 1 }; triangles.Add(vertices[0]); triangles.Add(vertices[1]); triangles.Add(vertices[2]); triangles.Add(vertices[2]); triangles.Add(vertices[1]); triangles.Add(vertices[3]); } bool isOverVertices = nextBaseIndex + lineVerticesCount > PerSegmentMaxVertices; bool isEndLine = (i == lineCount - 2); bool needGenerateSegment = isOverVertices || isEndLine; if (needGenerateSegment) { string segmentName = $"{name}-{material.name}-{newGeneratedTransform.Count + 1}"; Transform segmentTransform = generated.transform.Find(segmentName); if (null == segmentTransform) { var go = UOUtility.Create(segmentName, generated, typeof(MeshFilter), typeof(MeshRenderer), typeof(MeshCollider)); segmentTransform = go.transform; } segmentTransform.gameObject.isStatic = generated.isStatic; segmentTransform.gameObject.layer = generated.layer; newGeneratedTransform.Add(segmentTransform); generatedChildren.Remove(segmentTransform); var meshFilter = segmentTransform.GetComponent <MeshFilter>(); var meshRenderer = segmentTransform.GetComponent <MeshRenderer>(); var meshCollider = segmentTransform.GetComponent <MeshCollider>(); Mesh mesh = meshFilter.sharedMesh; if (null == mesh || mesh.name != segmentName) { mesh = new Mesh(); } else if (mesh.vertexCount != bentVertices.Count) { mesh.Clear(); } mesh.name = segmentName; mesh.hideFlags = HideFlags.HideInHierarchy; mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt16; var segmentBentVertices = bentVertices.GetRange(0, nextBaseIndex + lineVerticesCount); mesh.SetVertices(segmentBentVertices.Select(b => b.position).ToList()); mesh.SetNormals(segmentBentVertices.Select(b => b.normal).ToList()); mesh.SetUVs(0, segmentBentVertices.Select(b => b.uv).ToList()); mesh.SetTriangles(triangles, 0, false); mesh.RecalculateBounds(); mesh.RecalculateTangents(); meshFilter.sharedMesh = mesh; meshRenderer.material = material; meshCollider.sharedMesh = mesh; meshCollider.enabled = generateCollider; triangles.Clear(); bentVertices.RemoveRange(0, nextBaseIndex); nextBaseIndex = 0; } baseIndex = nextBaseIndex; } foreach (var deprecatedTransform in generatedChildren) { if (deprecatedTransform != null) { UOUtility.Destroy(deprecatedTransform.gameObject); } } }