Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by -OTTO- · Jul 22, 2016 at 05:18 PM · procedural meshwallsbezierroads

Procedural mesh, using beziers for walls and roads

Hello. I have been trying to make a system for creating procedural walls (and roads) using beziers. Something something along the lines of the road system in Cities Skylines. My first idea was to use premade geometry and instantiate wallsegments at fixed intervals. But since i want to have the walls join at points on towers and buildings, the length of the walls has to be very precise. So I have been looking at procedural meshes and bezier splines and after scouring the web, I kindof made a somewhat usable piece of code. The tutorials I have found have been very specific and I am just not experianced enough with coding to be able to figure this out.

https://drive.google.com/folderview?id=0B4S0tkWTFjF3YjU0T2piZVM0eHM&usp=sharing Here is a link to the unity project.

Below I have posted the code i have stitched together from bits and pieces found on the web and altered to be somewhat consistent...

When the mouse is clicked you can drag the cursor to create a line of verticies. If shift is held down the wall can be curved. I can alter the height of the wall by adding more segments in the Y direction. The cursor snaps to the closest end point of existing walls.

But now I am lost. Adding triangles in a loop to the verticies is a nightmare. And how do i offset the verticies from the center of the line, and set their rotation to fit the curvature and direction of the wall?

I hope someone can help me. If you can point me to some other way to create procedural walls at runtime, that would be allso be fantastic. I have found several eksamples of this, but no tutoruals. I am so close! :) http://architred.blogspot.dk/2013/05/unity-wall-tool.html <-- this guy made it

 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 using System;
 
 public class NewWall : MonoBehaviour
 {
 
     bool creating;
 
 
     public GameObject start;
     public GameObject end;
     public GameObject bezier;
 
     public GameObject adfa;
 
     public LayerMask wallLayer;
 
     public GameObject wallPolePoint;
 
     public int WallHeight = 3;
 
     bool poleSnapping;
     bool endPoleSnapping;
     bool isCurving;
 
     List<GameObject> poles;
 
     // Use this for initialization
     void Start()
     {
         poles = new List<GameObject>();
     }
 
     // Update is called once per frame
     void Update()
     {
         startCursor();
         getInput();
 
     }
 
     Vector3 getWorldPoint()
     {
 
         Ray ray = GameObject.FindGameObjectWithTag("MainCamera").GetComponent<Camera>().ScreenPointToRay(Input.mousePosition);
         RaycastHit hit;
 
         if (Physics.Raycast(ray, out hit, Mathf.Infinity, ~wallLayer))
         {
             return hit.point;
         }
         return Vector3.zero;
 
 
     }
 
 
     void getInput()
     {
         end.SetActive(false);
         bezier.SetActive(false);
 
         if (Input.GetMouseButtonDown(0))
         {
             setStart();
             end.SetActive(true);
             bezier.SetActive(true);
 
         }
 
         if (Input.GetKeyDown(KeyCode.LeftShift))
         {
 
             setBezier();
             isCurving = true;
 
         }
 
         if (Input.GetKeyUp(KeyCode.LeftShift))
         {
 
             isCurving = false;
 
         }
 
 
         else if (Input.GetMouseButtonUp(0))
         {
             setEnd();
             StartCoroutine(createWallSegments());
             isCurving = false;
 
         }
         else
         {
             if (creating)
             {
                 adjust();
                 end.SetActive(true);
                 bezier.SetActive(true);
             }
         }
 
     }
 
     Vector3 gridSnap(Vector3 originalPosition)
     {
         int granularity = 1;
         Vector3 snappedPosition = new Vector3(Mathf.Floor((originalPosition.x / granularity) * granularity), originalPosition.y, Mathf.Floor(originalPosition.z / granularity) * granularity);
         return snappedPosition;
 
     }
 
     void startCursor()
     {
         if (creating)
         {
             adjust();
         }
 
         else
         {
 
             if (GameObject.FindGameObjectsWithTag("Pole").Length == 0)
             {
 
                 start.transform.position = gridSnap(getWorldPoint());
 
                 poleSnapping = false;
 
             }
 
             else if
                 (Vector3.Distance((getWorldPoint()), closestPoleTo(getWorldPoint()).transform.position) <= 5)
             {
                 start.transform.position = closestPoleTo(getWorldPoint()).transform.position;
                 poleSnapping = true;
             }
 
             else
             {
                 start.transform.position = gridSnap(getWorldPoint());
                 poleSnapping = false;
 
             }
 
         }
 
     }
 
     void setStart()
     {
         creating = true;
         start.transform.position = gridSnap(getWorldPoint());
 
         if (poleSnapping)
         {
             start.transform.position = closestPoleTo(getWorldPoint()).transform.position;
         }
 
         GameObject p1 = (GameObject)Instantiate(wallPolePoint, start.transform.position, start.transform.rotation);
 
         p1.tag = "Pole";
 
         poles.Add(p1);
 
     }
 
 
 
     void setEnd()
     {
         creating = false;
         end.transform.position = gridSnap(getWorldPoint());
 
         if (endPoleSnapping)
         {
             end.transform.position = closestPoleTo(getWorldPoint()).transform.position;
         }
 
         GameObject p2 = (GameObject)Instantiate(wallPolePoint, end.transform.position, end.transform.rotation);
 
         p2.tag = "Pole";
 
         poles.Add(p2);
 
     }
 
     void setBezier()
     {
         creating = true;
         bezier.transform.position = gridSnap(getWorldPoint());
 
     }
 
 
     GameObject closestPoleTo(Vector3 worldPoint)
     {
         GameObject closest = null;
         float distance = Mathf.Infinity;
         float currentDistance = Mathf.Infinity;
         foreach (GameObject p in poles)
         {
             currentDistance = Vector3.Distance(worldPoint, p.transform.position);
             if (currentDistance < distance)
             {
                 distance = currentDistance;
                 closest = p;
             }
         }
         return closest;
     }
 
 
     void adjust()
     {
         if (GameObject.FindGameObjectsWithTag("Pole").Length == 0)
         {
 
             end.transform.position = gridSnap(getWorldPoint());
             endPoleSnapping = false;
 
         }
 
         else if
             (Vector3.Distance((getWorldPoint()), closestPoleTo(getWorldPoint()).transform.position) <= 5)
         {
             end.transform.position = closestPoleTo(getWorldPoint()).transform.position;
             endPoleSnapping = true;
         }
 
         else
         {
             end.transform.position = gridSnap(getWorldPoint());
             endPoleSnapping = false;
         }
 
 
         adjustWall();
     }
 
 
 
 
     void adjustWall()
     {
 
         Vector3 endTargetPostition = new Vector3(end.transform.position.x, start.transform.position.y, end.transform.position.z);
 
         Vector3 startTargetPostition = new Vector3(start.transform.position.x, end.transform.position.y, start.transform.position.z);
 
         start.transform.LookAt(endTargetPostition);
 
         end.transform.LookAt(startTargetPostition);
 
         Vector3 Distance = (start.transform.position + end.transform.position) / 2f;
 
         if (isCurving == false)
         {
 
             bezier.transform.position = Distance;
         }
 
     }
 
 
 //---------------------------------------------------------------------
 //this is the mesh generation code
 //---------------------------------------------------------------------
 
       List<Vector3> vertices = new List<Vector3>();
 
     private IEnumerator createWallSegments()
     {
         WaitForSeconds wait = new WaitForSeconds(0.05f);
 
         Mesh mesh = new Mesh();
 
 
         float distance = Mathf.Floor(Vector3.Distance(start.transform.position, end.transform.position) / 2);
 
         int distanceInt = Convert.ToInt32(distance);
 
         // set points of quadratic Bezier curve
         Vector3 p0 = start.transform.position;
         Vector3 p1 = bezier.transform.position;
         Vector3 p2 = end.transform.position;
         float t;
         Vector3 position;
 
         for (int i = 0, x = 0; x <= distance; x++)
         {
             for (int y = 0; y < WallHeight; y++, i++)
             {
                 t = x / (distance);
 
                 position = (1.0f - t) * (1.0f - t) * p0 + 2.0f * (1.0f - t) * t * p1 + t * t * p2;
 
 
                 Vector3 newPos = new Vector3(position.x, position.y + y, position.z);
 
                 vertices.Add(newPos);
 
                 yield return wait;
             }
 
         }
 
         mesh.vertices = vertices.ToArray();
 
         Debug.Log(mesh.vertices.Length);
 
 
         //List<int> triangles = new List<int>(mesh.triangles);
         
         int[] triangles = new int[mesh.vertices.Length * 6];
 
         for (int ti = 0, vi = 0, x = 0; x < WallHeight; x++, ti += 6, vi++)
         {
 
             triangles[ti] = vi;
 
             triangles[ti + 3] = triangles[ti + 1] = vi + 1;
 
             triangles[ti + 2] = triangles[ti + 5] = vi + WallHeight;
 
             triangles[ti + 4] = vi + WallHeight + 1;
         }
         
         //I am able to make the first row, but I am at a loss on how to loop this code. Everything I have tryed have
         //resultet in some strange behavior, with missing quads, half the wall facing the wrong way, or triangles joining
         // verts on the far side of the wall.. 
 
 
         mesh.triangles = triangles;
 
         //mesh.triangles = triangles.ToArray();
 
 
         MeshFilter filter = GetComponent<MeshFilter>();
 
         if (filter != null)
         {
             filter.sharedMesh = mesh;
         }
 
 
     }
 
 
 
     private void OnDrawGizmos()
     {
         if (vertices == null)
         {
             return;
         }
         Gizmos.color = Color.black;
         for (int i = 0; i < vertices.Count; i++)
         {
             Gizmos.DrawSphere(vertices[i], 0.1f);
         }
     }
 
 }

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
â–¼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

0 Replies

· Add your reply
  • Sort: 

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

3 People are following this question.

avatar image avatar image avatar image

Related Questions

Filling the space between bezier curves with a texture, 1 Answer

detect if two objects in a list intersect in editor. 0 Answers

Extrude shape with sharp corners 0 Answers

Mesh generated from bezier curve loop going outside loop 0 Answers

iTween for Dynamically Moving Objects around a Sphere 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges