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 /
avatar image
0
Question by Constantin_de · Aug 10, 2021 at 05:45 PM · collidermeshcolliderprocedural meshprocedural generationisland

How do I add a MeshCollider to my randomly generated island through Code

Hi, so im working on a procedural generated isand (like in the game "Muck" from Dani) but i am struggeling with adding colliders to the mesh through code. It would be great if someone could help me with that. The Code is from this Video: https://www.youtube.com/watch?v=COmtTyLCd6I&list=RDCMUCmtyQOKKmrMVaKuRXz02jbQ∈dex=3

He also made a tutorial about including colliders, but he is implementing it in a script for procedural generation and i dont really need that. Anyway, here is my code where i would like to include the mesh collider script:

 using UnityEngine;
 using System.Collections;
 public static class MeshGenerator 
 {
     
     public static MeshData GenerateTerrainMesh(float[,] heightMap, float heightMultiplier, 
     AnimationCurve heightCurve, int levelOfDetail)
     {
         int width = heightMap.GetLength (0);
         int height = heightMap.GetLength (1);
         float topLeftX = (width -1) / -2f;
         float topLeftZ = (height -1) / 2f;
         int meshSimplificationIncrement = (levelOfDetail ==0)?1:levelOfDetail * 2;
         int verticesPerLine = (width-1)/meshSimplificationIncrement + 1;
         MeshData meshData = new MeshData(verticesPerLine, verticesPerLine);
         int vertexIndex = 0;
         for(int y = 0; y <height; y+= meshSimplificationIncrement)
         {
             for(int x = 0; x < width; x+= meshSimplificationIncrement)
             {
                 meshData.vertices[vertexIndex] = new Vector3(topLeftX + x, heightCurve.Evaluate( 
                 heightMap[x,y]) * heightMultiplier, topLeftZ - y);
                 meshData.uvs[vertexIndex] = new Vector2(x/(float)width,y/(float)height);
                 if(x < width -1 && y < height -1)
                 {
                     meshData.AddTriangle(vertexIndex, vertexIndex+ verticesPerLine + 1, vertexIndex + 
                     verticesPerLine);
                     meshData.AddTriangle(vertexIndex + verticesPerLine + 1, vertexIndex, vertexIndex + 1);
                 }
                 
                 vertexIndex++;
             }
         }
         return meshData;
     }
 }
 public class MeshData
 {
     public Vector3[] vertices;
     public int[] triangles;
     public Vector2[] uvs;
     int triangleIndex;
     public MeshData(int meshWidth, int meshHeight)
     {
         vertices = new Vector3[meshWidth * meshHeight];
         uvs = new Vector2[meshWidth * meshHeight];
         triangles = new int[(meshWidth-1)*(meshHeight-1)*6];
     }
     public void AddTriangle(int a, int b, int c)
     {
         triangles [triangleIndex] = a;
         triangles [triangleIndex+1] = b;
         triangles [triangleIndex+2] = c;
         triangleIndex += 3;
     }
     public Mesh CreateMesh()
     {
         
         Mesh mesh = new Mesh();
         mesh.vertices = vertices;
         mesh.triangles = triangles;
         mesh.uv = uvs;
         mesh.RecalculateNormals();
         return mesh;
     }
 }

It could be possible that the collider has to be included in one of the other scripts, but i think that should be the right one. If you can help me with this, thank you very much 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

2 Replies

· Add your reply
  • Sort: 
avatar image
1

Answer by andrew-lukasik · Aug 11, 2021 at 08:28 PM

How do I add a MeshCollider?

Idk, easily?

MeshGeneratorTester.cs

 using UnityEngine;
 
 [RequireComponent( typeof(MeshFilter) )]
 [RequireComponent( typeof(MeshRenderer) )]
 [RequireComponent( typeof(MeshCollider) )]
 class MeshGeneratorTester : MonoBehaviour
 {
     [SerializeField] int _width = 101;
     [SerializeField] int _height = 101;
     [SerializeField] AnimationCurve _heightCurve = new AnimationCurve( new Keyframe(0,0) , new Keyframe(1,1) );
     Mesh _mesh;
     #if UNITY_EDITOR
     void OnValidate ()
     {
         if( _mesh!=null )
         {
             if( Application.isPlaying ) Object.Destroy( _mesh );
             else Object.DestroyImmediate( _mesh );
         }
         float[,] heightmap = new float[_width,_height];
         for( int y=0 ; y<_height ; y++ )
         for( int x=0 ; x<_width ; x++ )
         {
             heightmap[x,y] = Random.Range( 0 , 1f );
         }
         var meshdata = MeshGenerator.GenerateTerrainMesh( heightmap , 10f , _heightCurve , 1 );
         _mesh = meshdata.CreateMesh();
         GetComponent<MeshFilter>().sharedMesh = _mesh;
         GetComponent<MeshCollider>().sharedMesh = _mesh;
     }
     #endif
 }
 public static class MeshGenerator
 {
     public static MeshData GenerateTerrainMesh (
         float[,] heightMap ,
         float heightMultiplier ,
         AnimationCurve heightCurve ,
         int levelOfDetail
     )
     {
         int width = heightMap.GetLength(0);
         int height = heightMap.GetLength(1);
         float topLeftX = (width -1) / -2f;
         float topLeftZ = (height -1) / 2f;
         int meshSimplificationIncrement = (levelOfDetail ==0)?1:levelOfDetail * 2;
         int verticesPerLine = (width-1) / meshSimplificationIncrement + 1;
         MeshData meshData = new MeshData( verticesPerLine , verticesPerLine );
         int vertexIndex = 0;
         for( int y=0 ; y<height ; y+=meshSimplificationIncrement )
         for( int x=0 ; x<width ; x+=meshSimplificationIncrement )
         {
             meshData.vertices[vertexIndex] = new Vector3(
                 topLeftX + x ,
                 heightCurve.Evaluate( heightMap[x,y]) * heightMultiplier ,
                 topLeftZ - y
             );
             meshData.uvs[vertexIndex] = new Vector2(
                 x / (float)width ,
                 y / (float)height
             );
             if( x<width-1 && y<height-1 )
             {
                 meshData.AddTriangle( vertexIndex , vertexIndex+verticesPerLine+1 , vertexIndex+verticesPerLine );
                 meshData.AddTriangle( vertexIndex+verticesPerLine+1 , vertexIndex , vertexIndex+1 );
             }
             
             vertexIndex++;
         }
         return meshData;
     }
 }
 
 public class MeshData
 {
     public Vector3[] vertices;
     public int[] triangles;
     public Vector2[] uvs;
     int triangleIndex;
     public MeshData(int meshWidth, int meshHeight)
     {
         vertices = new Vector3[meshWidth * meshHeight];
         uvs = new Vector2[meshWidth * meshHeight];
         triangles = new int[(meshWidth-1)*(meshHeight-1)*6];
     }
     public void AddTriangle(int a, int b, int c)
     {
         triangles [triangleIndex] = a;
         triangles [triangleIndex+1] = b;
         triangles [triangleIndex+2] = c;
         triangleIndex += 3;
     }
     public Mesh CreateMesh()
     {
         Mesh mesh = new Mesh();
         mesh.vertices = vertices;
         mesh.triangles = triangles;
         mesh.uv = uvs;
         mesh.RecalculateNormals();
         return mesh;
     }
 }

alt text


screenshot-2021-08-12-004544.jpg (146.8 kB)
Comment
Add comment · Show 6 · 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
avatar image Constantin_de · Aug 11, 2021 at 10:36 PM 0
Share

Ok, so first of all thanks a lot for helping me out, I saw the answer and jumped out of the bed to test it. I coudnt get it to work though. Is there anything special I have to do or is it supposed to work like this? Maybe its because the collider has to be scaled up by 10,10,10 since the mesh is also scaled up like that, but i dont think that was the issue since not even a small meshcollider showed up. I also tried it with the scene of episode 11 of Sebastian Lagues tutorial but that also didnt work. I already got some of it working myself, but the code still has some bugs, since it spawns 5 of the colliders at a time and continues with it if the mouse touches the MapGenerator. I'll include some of that code, but i dont think its relevant since your method looks more promising.

      MeshCollider meshCollider;
      GameObject meshObject;
 
      public Mesh CreateMesh()
      {
 
          Mesh mesh = new Mesh();
          mesh.vertices = vertices;
          mesh.triangles = triangles;
          mesh.uv = uvs;
          mesh.RecalculateNormals();
            
          meshObject = new GameObject("terrainCollider");
          meshCollider = meshObject.AddComponent<MeshCollider>();
          meshObject.transform.localScale = new Vector3(10, 10, 10);
          meshCollider.sharedMesh = mesh;
 
          return mesh;
 
      }


avatar image andrew-lukasik Constantin_de · Aug 11, 2021 at 10:49 PM 0
Share

It works fine, see the attached image. What was missing is _heightCurve set to anything (updated the code so it contains default value there)

If you disable that Mesh Renderer component you will see a green collision mesh underneath it. But word of warning: mesh colliders (non-convex) are the worst case of all kinds of colliders (costly & very low precision).

avatar image Constantin_de andrew-lukasik · Aug 12, 2021 at 04:17 PM 0
Share

So that sadly didnt work neither. It generates a mesh collider but it looks very weird, like on the screenshot you attached up there. I also get this error message:

SendMessage cannot be called during Awake, CheckConsistency, or OnValidate UnityEngine.StackTraceUtility:ExtractStackTrace () MeshGeneratorTester:OnValidate () (at Assets/Scripts/MeshGeneratorTester.cs:28) UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&)

The best result so far was with the method I sent you up there, since I was able to get the collider working and in the right shape. But its probably in the wrong class, since it spawns way to much coliders and also wont stop with it.

Need to add these two features too:
- Only add collider while playing - automaticaly adjusting the collider to different seeds and changes too the map (since its a procedual map). If you got any ideas for these two it would be great if you could write them. This would probably save me a "few" hours. Annyway thanks a lot for your help, gotta add you too the game credits if i should ever finish that project ;)

alt text

alt text

(Second one is how it should look)

unityscreen2.jpg (210.7 kB)
Show more comments
avatar image
1

Answer by Constantin_de · Aug 17, 2021 at 04:18 PM

I finally did it!! Its a bit painfull to see how easy it actually was, but im very glad i figured it out. The only thing i did was to add this small script to my Mesh object:

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
     public class AddCollider : MonoBehaviour
     {
         GameObject mesh;
     
         void Awake()
         {
             mesh = GameObject.Find ("Mesh");
             mesh.AddComponent<MeshCollider>();
         }
     
     }

@andrew-lukasik thanks for your answers, you gave me the idea to put the script directly on the Mesh! Man, I really do love programming :DD

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

212 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

Related Questions

Rigidbody projectile gets stuck in two-sided Procedural mesh / mesh collider 0 Answers

Problem with colliders going through platforms 2 Answers

Problem with colliders 2 Answers

UV problem on procedural mesh generation 1 Answer

Procedural realistic terrain for hex tile map - what's causing the edges to stick up? 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