As in Unity3D , for a 2D game, draw arbitrary lines using tangencies (although it seems to me that the mouse is still the same).

For example, I clicked on the screen, drew an arbitrary circle, after which the finger was removed and this object was created, and the Rigidbody2D component was added as far as possible, and the correct collision mask would not be a square, which borders the region around the edges, but a curve. And as far as I know, Rigidbody and MeshCollider do not work together (but this is in 3D ).

  • You can use Line Renderer to draw lines docs.unity3d.com/en/current/Manual/class-LineRenderer.html ....... why do you need collision and Rigidbody? What do you want to achieve in the end? - Alexey Shimansky
  • @ Alexey Shimansky, is it possible to adequately hang a rigidbody and a collider on this line? - Jaroslav Movchan
  • I doubt .... the line is a set of points. If you hang a collider, it is not on a specific line, but on small intervals between points, each (for example) two pieces ...... Generally depends on the task .. If you do damage you don’t even have to hang colliders - Alexey Shimansky

1 answer 1

We draw a line from point to point using two triangles, create a MeshRenderer and create a line for it from point to point, complementing it. The code from our project, took an example from the network, drew 2D graphics. For physics, you can then hang on a Rigidbody2D object and try either PolygonCollider2D, or you have to hang BoxCollider2D on each line.

Here is the code for the line drawing class added by points during the drawing process.

 using UnityEngine; using System; using System.Collections; using System.Collections.Generic; using System.Threading; using ThreadPriority = System.Threading.ThreadPriority; [RequireComponent (typeof (MeshFilter))] /// <summary> /// Generates a trail that is always facing upwards using the scriptable mesh interface. /// vertex colors and uv's are generated similar to the builtin Trail Renderer. /// To use it /// 1. create an empty game object /// 2. attach this script and a MeshRenderer /// 3. Then assign a particle material to the mesh renderer /// </summary> public class Line : MonoBehaviour { public float height = 2.0f; public float time = 2.0f; public bool localDraw = false; public float minDistance = 0.1f; public Color startColor = Color.white; public Color endColor = new Color (1, 1, 1, 0); [HideInInspector] public Mesh mesh; protected List<TrailSection> sections; protected TrailSection lastSection; private float testNormal = 1.0f; private Transform cachedTransform; private Vector3[] vertices; private Color[] colors; private Vector2[] uv; private Vector3[] normals; private int[] triangles; private bool needUpdate = false; private Thread threadCalcMesh; private object lockOn = new object(); // Use this for initialization protected virtual void Awake () { // Rebuild the mesh cachedTransform = transform; mesh = GetComponent<MeshFilter>().mesh; Clear(); /*AddPoint(new Vector3(0.0f,0.0f)); AddPoint(new Vector3(5.0f,4.0f)); AddPoint(new Vector3(8.0f,2.0f)); AddPoint(new Vector3(10.0f,12.0f)); ReDraw();*/ } virtual public void Clear() { mesh.Clear(); sections = new List<TrailSection>(); lastSection = null; transform.localScale = Vector3.one; } // Update is called once per frame void Update () { /*if (Input.GetKeyDown(KeyCode.Space)){ // this.AddPoint(Input.mousePosition); testNormal *= -1; Sender.SendEventHierarchy(EventDiagram.UPDATE, this); }*/ if (needUpdate) { //if (Monitor.TryEnter(lockOn)) lock (lockOn) { mesh.Clear(); mesh.vertices = vertices; mesh.colors = colors; mesh.uv = uv; mesh.triangles = triangles; mesh.normals = normals; needUpdate = false; } } } virtual public void ReDraw(){ MeshUpdate(); } virtual protected void OnEnable(){ Sender.SendEventHierarchy(EventDiagram.UPDATE, this); } virtual protected void OnDisable(){ } virtual public void AddPoint(Vector3 position){ Vector3 vDistance = Vector3.zero; if (lastSection != null){ vDistance = lastSection.point - position; vDistance.Scale(transform.localScale); } // Add a new trail section if (lastSection == null || vDistance.sqrMagnitude > minDistance * minDistance) { var section = new TrailSection(); section.point = position; if (localDraw) section.forwardDir = Vector3.forward; else section.forwardDir = transform.TransformDirection(Vector3.forward); sections.Add(section); lastSection = section; } updateAfterAddPoint(); } virtual protected void updateAfterAddPoint(){ } public void MeshUpdate () { // We need at least 2 sections to create the line if (sections.Count < 2) return; if (threadCalcMesh != null && threadCalcMesh.IsAlive) return; threadCalcMesh = new Thread(recalcMesh); threadCalcMesh.IsBackground = true; threadCalcMesh.Priority = ThreadPriority.BelowNormal; threadCalcMesh.Start(getVectorScale()); //thread.Join(); } void recalcMesh(object scaleV) { int sectCount = sections.Count; int vert = (sectCount - 1) * 4; Vector3[] vertices = new Vector3[vert]; Color[] colors = new Color[vert]; Vector2[] uv = new Vector2[vert]; Vector3[] normals = new Vector3[vert]; TrailSection previousSection;// = sections[0]; TrailSection currentSection = sections[0]; TrailSection nextSection;// = sections[0]; // Use matrix instead of transform.TransformPoint for performance reasons //Matrix4x4 localSpaceTransform = transform.worldToLocalMatrix; Vector3 upDir, upDirCross; Vector3 vec; Vector3 vec1, vec2, vecCross; int idx; Vector3 vectorScale = (Vector3) scaleV; // Generate vertex, uv and colors for (int i = 1; i < sectCount; i++) { previousSection = currentSection; currentSection = sections[i]; if (i < sectCount - 1) nextSection = sections[i + 1]; else nextSection = currentSection; // Calculate u for texture uv and color interpolation vec = currentSection.point - previousSection.point; vec1 = currentSection.point - previousSection.point; vec2 = currentSection.point - nextSection.point; vecCross = Vector3.Cross(vec1, vec2); // Calculate upwards direction upDir = Vector3.Cross(-vec, Vector3.forward); upDir.Normalize(); upDir *= height / 2; upDir = Vector3.Scale(upDir, vectorScale); idx = (i - 1) * 4; if (i == 1) { vertices[idx + 0] = previousSection.point - upDir; vertices[idx + 1] = previousSection.point + upDir; } else { vertices[idx + 0] = previousSection.crossUp ? previousSection.point - upDir : vertices[idx - 2]; vertices[idx + 1] = !previousSection.crossUp ? previousSection.point + upDir : vertices[idx - 1]; ; } if (i + 1 == sectCount) { vertices[idx + 2] = currentSection.point - upDir; vertices[idx + 3] = currentSection.point + upDir; } else { // ΠΈΡ‰Π΅ΠΌ Ρ‚ΠΎΡ‡ΠΊΡƒ пСрСсСчСния сСкции со ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ сСкциСй currentSection.crossUp = Vector3.Dot(vecCross, currentSection.forwardDir) < 0; upDirCross = Vector3.Cross(vec2.normalized - vec1.normalized, currentSection.forwardDir); //upDirCross = vec1 + vec2; upDirCross.Normalize(); //float sinb = Vector3.Cross(vec1.normalized, vec2.normalized).magnitude; upDirCross *= height / 2;// / sinb; upDirCross = Vector3.Scale(upDirCross, vectorScale); // Поиск Ρ‚ΠΎΡ‡ΠΊΠΈ ΠΊΠ°ΠΊ сумму Π²Π΅ΠΊΡ‚ΠΎΡ€ΠΎΠ² /*vec1.Normalize(); vec1 *= height / 2; vec1 = Vector3.Scale(vec1, vectorScale); vec2.Normalize(); vec2 *= height / 2; vec2 = Vector3.Scale(vec2, vectorScale); upDirCross = -vec1 - vec2;*/ if (currentSection.crossUp) { vertices[idx + 2] = currentSection.point - upDir; vertices[idx + 3] = currentSection.point + upDirCross; } else { vertices[idx + 2] = currentSection.point - upDirCross; vertices[idx + 3] = currentSection.point + upDir; } } float u = 0.0f; u = Mathf.Clamp01((float)(i - 1) / sectCount); uv[idx + 0] = new Vector2(u, 0); uv[idx + 1] = new Vector2(u, 1); u = Mathf.Clamp01((float)i / sectCount); uv[idx + 2] = new Vector2(u, 0); uv[idx + 3] = new Vector2(u, 1); // fade colors out over time Color interpolatedColor = Color.Lerp(startColor, endColor, u); colors[idx + 0] = interpolatedColor; colors[idx + 1] = interpolatedColor; colors[idx + 2] = interpolatedColor; colors[idx + 3] = interpolatedColor; normals[idx + 0] = currentSection.forwardDir * testNormal; normals[idx + 1] = currentSection.forwardDir * testNormal; normals[idx + 2] = currentSection.forwardDir * testNormal; normals[idx + 3] = currentSection.forwardDir * testNormal; } // Generate triangles indices int[] triangles = new int[(sectCount - 1) * 6 + (sectCount - 2) * 3]; int sectionNum = 1; int idx4, idx9; float cntStep = ((float)triangles.Length) / 9; for (int i = 0; i < cntStep; i++) { idx9 = i * 9; idx4 = i * 4; //ΠŸΠ΅Ρ€Π²Ρ‹ΠΉ Ρ‚Ρ€Π΅ΡƒΠ³ΠΎΠ»ΡŒΠ½ΠΈΠΊ triangles[idx9 + 0] = idx4; triangles[idx9 + 1] = idx4 + 1; triangles[idx9 + 2] = idx4 + 2; //Π’Ρ‚ΠΎΡ€ΠΎΠΉ Ρ‚Ρ€Π΅ΡƒΠ³ΠΎΠ»ΡŒΠ½ΠΈΠΊ triangles[idx9 + 3] = idx4 + 2; triangles[idx9 + 4] = idx4 + 1; triangles[idx9 + 5] = idx4 + 3; if (sectionNum + 1 == sectCount) break; //ΡΠΎΠ΅Π΄ΠΈΠ½ΡΡŽΡ‰ΠΈΠΉ Ρ‚Ρ€Π΅ΡƒΠ³ΠΎΠ»ΡŒΠ½ΠΈΠΊ if (sections[sectionNum].crossUp) { triangles[idx9 + 6] = idx4 + 2; triangles[idx9 + 7] = idx4 + 3; triangles[idx9 + 8] = idx4 + 4; } else { //ΡΠΎΠ΅Π΄ΠΈΠ½ΡΡŽΡ‰ΠΈΠΉ Ρ‚Ρ€Π΅ΡƒΠ³ΠΎΠ»ΡŒΠ½ΠΈΠΊ triangles[idx9 + 6] = idx4 + 2; triangles[idx9 + 7] = idx4 + 3; triangles[idx9 + 8] = idx4 + 5; } sectionNum++; } lock (lockOn) { this.vertices = vertices; this.colors = colors; this.uv = uv; this.triangles = triangles; this.normals = normals; needUpdate = true; } } protected Vector3 getVectorScale(){ return new Vector3(1 / transform.localScale.x, 1/ transform.localScale.y, 1 / transform.localScale.z); } } 

I warn the code from the project, so there may be some tails, such as calling external events, etc. How to use seems to be in the comments

  • I'll wait for the code, perhaps), and thanks for the direction in which to look for) - Jaroslav Movchan
  • one
    @ YaroslavMovchan added the code - KingPeas