Пример #1
0
        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);
        }
Пример #2
0
        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);
            }
        }
Пример #3
0
        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);
            }
        }
Пример #4
0
        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);
            }
        }
Пример #5
0
        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);
            }
        }
Пример #6
0
        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);
                }
            }
        }
Пример #7
0
        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);
                }
            }
        }