Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice
  2. Ever participated in one our Game Jams? Want pointers on your project? Our Evangelists will be available on Friday to give feedback. Come share your games with us!
    Dismiss Notice

ProBuilder Extruding along a line programmatically

Discussion in 'World Building' started by Skaltum, Aug 11, 2019.

  1. Skaltum

    Skaltum

    Joined:
    Nov 1, 2013
    Posts:
    11
    I'm trying to create a script that will extrude a face along a path but I can't quite get there.
    I don't know how I can get the indices of the vertices I created using extrude.

    This is what I currently have:


    What I want is a full ring without the holes.

    This is my code:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using UnityEngine;
    5. using UnityEngine.ProBuilder;
    6. using UnityEngine.ProBuilder.MeshOperations;
    7.  
    8. public class ProbuilderProceduralWall : MonoBehaviour
    9. {
    10.     public int radius = 10;
    11.     public int iterations = 20;
    12.     public bool FlipNormals = false;
    13.     [SerializeField]
    14.     List<Vector2> _face = new List<Vector2>();
    15.     [SerializeField]
    16.     Vector3[] _path = new Vector3[0];
    17.  
    18.     void OnDrawGizmos()
    19.     {
    20.         for (int i = 0; i < _face.Count - 1; i++)
    21.         {
    22.             Debug.DrawLine(_face[i], _face[i + 1]);
    23.         }
    24.         for (int i = 0; i < _path.Length - 1; i++)
    25.         {
    26.             Debug.DrawLine(_path[i], _path[i + 1]);
    27.         }
    28.     }
    29.     void Start()
    30.     {
    31.         if (_path.Length == 0) _path = MakePath(iterations, radius);
    32.         if (_face.Count == 0) _face = new List<Vector2>() { new Vector2(-0.5f, 0), new Vector2(-0.25f, .5f), new Vector2(0, 1), new Vector2(0.25f, 0.5f), new Vector2(0.5f, 0) };
    33.         Do();
    34.     }
    35.     void OnGUI()
    36.     {
    37.         if (GUILayout.Button("Make path"))
    38.         {
    39.             _path = MakePath(iterations, radius);
    40.         }
    41.  
    42.         if (GUILayout.Button("Do"))
    43.         {
    44.             Do();
    45.         }
    46.     }
    47.  
    48.     static Vector3[] MakePath(int iterations, float radius)
    49.     {
    50.         var path = new Vector3[iterations];
    51.         for (var i = 0; i < iterations; i++)
    52.         {
    53.             path[i] = new Vector3(Mathf.Sin((1f / iterations * Mathf.PI * 2) * i) * radius, 0, Mathf.Cos((1f / iterations * Mathf.PI * 2) * i) * radius);
    54.         }
    55.         return path;
    56.     }
    57.  
    58.     void Do()
    59.     {
    60.         var min = _face.Aggregate(new Vector2(Mathf.Infinity, Mathf.Infinity), (agg, p) => Vector2.Min(agg, p));
    61.         var max = _face.Aggregate(new Vector2(Mathf.NegativeInfinity, Mathf.NegativeInfinity), (agg, p) => Vector2.Max(agg, p));
    62.  
    63.         var mesh = ProBuilderMesh.Create();
    64.         var facePoints = new List<Vector3>(_face.Select(p => (Vector3)p));
    65.         facePoints.Sort((a, b) => a.x.CompareTo(b.x));
    66.         facePoints.Insert(0, new Vector3(min.x, min.y - 1));
    67.         facePoints.Add(new Vector3(max.x, min.y - 1));
    68.         mesh.CreateShapeFromPolygon(facePoints, 0, FlipNormals);
    69.         var instance = GameObject.Instantiate(mesh.gameObject);
    70.         var instanceMesh = instance.GetComponent<ProBuilderMesh>();
    71.  
    72.  
    73.         instanceMesh.transform.position = _path[0];
    74.         var toModel = instanceMesh.transform.worldToLocalMatrix;
    75.         var face = instanceMesh.faces.Last();
    76.         var faces = new[] { face };
    77.  
    78.         for (int i = 0; i < _path.Length - 1; i++)
    79.         {
    80.             var start = _path[i];
    81.             var middle = _path[i + 1];
    82.             var end = i + 2 < _path.Length ? _path[i + 2] : _path[i + 1];
    83.  
    84.             var createdFaces = instanceMesh.Extrude(faces, ExtrudeMethod.FaceNormal, 1);
    85.  
    86.             var positions = new List<Vector3>(instanceMesh.positions);
    87.             var dir = ((middle - start).normalized + (end - middle).normalized);
    88.             var rotation = Quaternion.LookRotation(dir, Vector3.up);
    89.             var toWorld = Matrix4x4.TRS(middle, rotation, Vector3.one);
    90.             Debug.DrawRay(middle, dir.normalized, Color.magenta, 30.0f);
    91.          
    92.             foreach (var index in face.distinctIndexes)
    93.             {
    94.                 positions[index] = toModel.MultiplyPoint3x4(toWorld.MultiplyPoint3x4(facePoints[index]));
    95.                 Debug.DrawRay(positions[index], Vector3.up * 0.1f, Color.red, 30.0f);
    96.             }
    97.             instanceMesh.positions = positions;          
    98.         }
    99.  
    100.         instanceMesh.ToMesh();
    101.         instanceMesh.Refresh();
    102.         instanceMesh.name = $"{name}";
    103.         instanceMesh.GetComponentInChildren<Renderer>().sharedMaterial = BuiltinMaterials.defaultMaterial;
    104.         Destroy(mesh.gameObject);
    105.         Debug.Log("Created mesh", instanceMesh);
    106.     }
    107.  
    108. }
    109.  
     
unityunity