Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 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 /
  • Help Room /
avatar image
0
Question by TheLittleGameDev · Jun 06, 2020 at 08:41 AM · scripting problemmeshscripting beginner

How to create a mesh at a location with code?

Hi, I´m new at C# and I´m triyng to learn more about procedural mesh generation.

I have a code where I create a landscape totally procedurally, but I want to add foliage.

I have two scripts: In the first one I create the landscape. In the second one, I get the vertices variable from the first one, and, using the location of the vertices of the mesh, I want to create one plant in each one. The loop is just for going through every vertices in the mesh.

Well, my question is how can I create a prefab in the position of this vertices.

 //This is the mesh generator (the first code)
 
 
 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 
 
 [RequireComponent(typeof(MeshFilter))]
 public class TerrainProceduralGeneratorScript : MonoBehaviour
 {
     //Variables
     Mesh mesh;
 
     public Vector3[] vertices;
     int[] triangles;
     Vector2[] uvs;
 
     public int xSize = 200;
     public int zSize = 200;
     public float globalAltitude = 5f;
 
 
     // Start is called before the first frame update
     void Start()
     {
         mesh = new Mesh();
         GetComponent<MeshFilter>().mesh = mesh;
         CreateShape();
         UpdateMesh();
     }
 
     //Create the shape of the mesh
     void CreateShape()
     {
         //Get the number of vertices depending on the size of the mesh
         vertices = new Vector3[(xSize + 1) * (zSize + 1)];
 
         //set the positions of all the vertices
         for (int i = 0, z = 0; z <= zSize; z++)
         {
             for (int x = 0; x <= xSize; x++)
             {
                 float y1 = Mathf.PerlinNoise(x * 1000f, z * 10f) * 1f;
                 float y2 = Mathf.PerlinNoise(x * 0.05f, z * 0.05f) * 1f;
                 float y3 = Mathf.PerlinNoise(x * 0.025f, z * 0.025f) * 2f;
                 float y4 = Mathf.PerlinNoise(x * 0.0125f, z * 0.0125f) * 3f;
 
                 float y = y1 * y2 * y3 * y4 * globalAltitude;
 
                 vertices[i] = new Vector3(x, y, z);
                 i++;
             }
         }
 
 
         //Defines the number of triangles it must have
         triangles = new int[xSize * zSize * 6];
 
         int vert = 0;
         int tris = 0;
 
 
         //Create the triangles
         for (int z = 0; z < zSize; z++)
         {
             for (int x = 0; x < xSize; x++)
             {
                 triangles[tris + 0] = vert + 0;
                 triangles[tris + 1] = vert + xSize + 1;
                 triangles[tris + 2] = vert + 1;
                 triangles[tris + 3] = vert + 1;
                 triangles[tris + 4] = vert + xSize + 1;
                 triangles[tris + 5] = vert + xSize + 2;
 
                 vert++;
                 tris += 6;
             }
             vert++;
         }
 
 
         //Creates a UV map using all the vertices
         uvs = new Vector2[vertices.Length];
 
         for (int i = 0, z = 0; z <= zSize; z++)
         {
             for (int x = 0; x <= xSize; x++)
             {
                 uvs[i] = new Vector2((float)x / xSize, (float)z / zSize);
                 i++;
             }
         }
     }
 
 
     //Update the mesh shape and create the mesh making it visible
     void UpdateMesh()
     {
         //Clean the mesh
         mesh.Clear();
 
         //Create all normals of the mesh
         mesh.RecalculateNormals();
 
         //Set the vertices, triangles and UV map of the mesh
         mesh.vertices = vertices;
         mesh.triangles = triangles;
         mesh.uv = uvs;
 
         //Creates collision for the mesh
         mesh.RecalculateBounds();
         MeshCollider meshCollider = gameObject.GetComponent<MeshCollider>();
         meshCollider.sharedMesh = mesh;
     }
     
     
     //Shows gizmos such as spheres on every vertices and lines on the normals
 
     /*
     private void OnDrawGizmos()
     {
         if (vertices == null)
             return;
 
         for (int i=0; i<vertices.Length; i++)
         {
             Gizmos.DrawSphere(vertices[i], 0.1f);
         }
     }
     */
 }

And the second code:

 //This is where I want to create the foliage prefab
 
 
 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class ProceduralFoliageScript : MonoBehaviour
 {
     //Variables
     public Vector3[] terrainVertices;
 
     void Start()
     {
 
     }
     
     void Update()
     {
         //Obtain all vertices positions in the landscape mesh
         GameObject terrain = GameObject.Find("ProceduralGenerator");
         TerrainProceduralGeneratorScript terrainScript = terrain.GetComponent<TerrainProceduralGeneratorScript>();
         terrainVertices = terrainScript.vertices;
     }
 
     void CreateFoliage()
     {
         //The loop pass through all the vertex positions of the mesh
         for (int i = 0, z = 0; z <= zSize; z++)
         {
             for (int x = 0; x <= xSize; x++)
             {
                 terrainVertices[i]
 
                 //Update the loop
                 i++;
             }
         }
     }
 }
 

And sorry if my code is bad, it´s because i've been working on other languages, but I am trying to learn C#.

And thanks in advance :)

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

1 Reply

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by SteenPetersen · Jun 06, 2020 at 08:43 AM

Here is a solution that I have tested as working, hope it helps and perhaps also show you some sanity checks and some good approaches to doing this sort of thing. (Note that we change your perlin noise so that we offset the perlin map, that way we get different generation every time.)

 using UnityEngine;
 
 [RequireComponent(typeof(MeshFilter))]
 public class ProceduralMap : MonoBehaviour
 {
     //Variables
     Mesh mesh;
     MeshCollider _myMeshCollider;
     MeshRenderer _myMeshRenderer;
 
     [Tooltip("The material that we wish to use for the Terrain")]
     [SerializeField] private Material terrainMaterial;
 
     public Vector3[] vertices;
     int[] triangles;
     Vector2[] uvs;
 
     // public properties
     public int XSize { get { return _xSize; } }
     [SerializeField] private int _xSize = 200;
 
     public int ZSize { get { return _zSize; } }
     [SerializeField] private int _zSize = 200;
 
     public float GlobalAltitude { get { return _globalAltitude; } }
     [SerializeField] private float _globalAltitude = 5f;
 
     //called before Start so we can call the foliage in Start
     void Awake()
     {
         mesh = new Mesh();
         GetComponent<MeshFilter>().mesh = mesh;
         CreateShape();
         UpdateMesh();
     }
 
     void CreateShape()
     {
         //Get the number of vertices depending on the size of the mesh
         vertices = new Vector3[(_xSize + 1) * (_zSize + 1)];
 
         Vector2 offset = new Vector2(Random.Range(0, 100), Random.Range(0, 100));

         //set the positions of all the vertices


     // NOTE that we change this so we can get an offset on the perlin Noise map so we get different   maps everytime


         for (int i = 0, z = 0; z <= _zSize; z++)
         {
             for (int x = 0; x <= _xSize; x++)
             {
                 float y1 = Mathf.PerlinNoise(x * 1000f + offset.x, z * 10f + offset.y) * 1f;
                 float y2 = Mathf.PerlinNoise(x * 0.05f + offset.x, z * 0.05f + offset.y) * 1f;
                 float y3 = Mathf.PerlinNoise(x * 0.025f + offset.x, z * 0.025f + offset.y) * 2f;
                 float y4 = Mathf.PerlinNoise(x * 0.0125f + offset.x, z * 0.0125f + offset.y) * 3f;

                 float y = y1 * y2 * y3 * y4 * _globalAltitude;

                 vertices[i] = new Vector3(x, y, z);
                 i++;
             }
         }
 
         //Defines the number of triangles it must have
         triangles = new int[_xSize * _zSize * 6];
 
         int vert = 0;
         int tris = 0;
 
 
         //Create the triangles
         for (int z = 0; z < _zSize; z++)
         {
             for (int x = 0; x < _xSize; x++)
             {
                 triangles[tris + 0] = vert + 0;
                 triangles[tris + 1] = vert + _xSize + 1;
                 triangles[tris + 2] = vert + 1;
                 triangles[tris + 3] = vert + 1;
                 triangles[tris + 4] = vert + _xSize + 1;
                 triangles[tris + 5] = vert + _xSize + 2;
 
                 vert++;
                 tris += 6;
             }
             vert++;
         }
 
 
         //Creates a UV map using all the vertices
         uvs = new Vector2[vertices.Length];
 
         for (int i = 0, z = 0; z <= _zSize; z++)
         {
             for (int x = 0; x <= _xSize; x++)
             {
                 uvs[i] = new Vector2((float)x / _xSize, (float)z / _zSize);
                 i++;
             }
         }
     }
 
 
     //Update the mesh shape and create the mesh making it visible
     void UpdateMesh()
     {
         //Clean the mesh
         mesh.Clear();
 
         //Set the vertices, triangles and UV map of the mesh
         mesh.vertices = vertices;
         mesh.triangles = triangles;
         mesh.uv = uvs;
 
         //Creates collision for the mesh
         if (_myMeshCollider == null)
         {
             if (TryGetComponent(out _myMeshCollider)) { }
             else
             {
                 _myMeshCollider = gameObject.AddComponent<MeshCollider>();
             }
         }
 
         mesh.RecalculateBounds();
         _myMeshCollider.sharedMesh = mesh;
 
         // render the mesh
         if (_myMeshRenderer == null)
         {
             if (TryGetComponent(out _myMeshRenderer)) { }
             else
             {
                 _myMeshRenderer = gameObject.AddComponent<MeshRenderer>();
             }
         }
 
         if (terrainMaterial != null)
             _myMeshRenderer.material = terrainMaterial;
         else
             _myMeshRenderer.material = new Material(Shader.Find("Standard"));

         //Create all normals of the mesh
         mesh.RecalculateNormals();  // note that we move this to he end
     }
 }


And then the Foliage generator:

 using UnityEngine;
 
 public class ProceduralFoliage : MonoBehaviour
 {
     //Variables
     [SerializeField] private Vector3[] terrainVertices;
     [SerializeField] private GameObject foliagePrefab;
 
     private ProceduralMap terrainScript;
     private GameObject foliageHolder; // just an empty gameObject to hold the foliage in hierarchy
 
     void Start()
     {
         //Obtain all vertices positions in the landscape mesh
         if(GameObject.Find("ProceduralGenerator").TryGetComponent(out terrainScript))
         {
             terrainVertices = terrainScript.vertices;
             CreateFoliage();
         }
         else
         {
             Debug.LogError("Cannot find the terrainScript");
         }
     }
 
     void CreateFoliage()
     {
         foliageHolder = new GameObject("foliageHolder");
 
         if (foliagePrefab == null)
             foliagePrefab = GameObject.CreatePrimitive(PrimitiveType.Capsule);
 
         //The loop pass through all the vertex positions of the mesh
         for (int i = 0, z = 0; z <= terrainScript.ZSize; z++)
         {
             for (int x = 0; x <= terrainScript.XSize; x++)
             {
                 Instantiate(foliagePrefab, terrainVertices[i], Quaternion.identity, foliageHolder.transform);
                 i++;
             }
         }
     }
 }


You could of course also add something like this to start adding foliage randomly:

 float tmp = Random.Range(0, 100);
 if (tmp < chanceToSpawnPerVertex)
 { 
     Instantiate(foliagePrefab, terrainVertices[i], Quaternion.identity, foliageHolder.transform);
     foliagePositions.Add(terrainVertices[i]); // keep track of the position so we later we can spawn other things and avoid these placements.
 }
 
 i++;


Result:

alt text


procgen.gif (240.3 kB)
Comment
Add comment · Share
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

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

323 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Destroy shattered objects after being smashed. 0 Answers

use MouseOnClick two times? 1 Answer

HELP ! Highscore name input after each Death 0 Answers

Possible Missing XML/DLL Files? 0 Answers

How can I temporary increase the size of an object? 2 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