Search Unity

Creating a Mesh which looks like a Chessboard in U3D

Discussion in 'Getting Started' started by romanpinkel, Sep 8, 2019.

  1. romanpinkel

    romanpinkel

    Joined:
    Sep 4, 2019
    Posts:
    17
    hello everyone,
    I've already googled a lot but cant find what I'm looking for.
    I'm creating a Plane with a grass texture. This is e.g. 5x5 metres.
    Now I want to texture it like a chessboard with grass/dirt. I just know how to give this plane one material (grass atm). How can I give it two textures? How can I manage the chessboard-look? Of course I want it all done by C#-code and not manually.

    this is the code im actually using:
    Code (CSharp):
    1. public static class Create_Terrain_Helper_Mono
    2. {
    3.     public static GameObject CreatePlaneMono (int width, int depth, bool collider, Material material)
    4.     {
    5.         GameObject go = new GameObject("Baustellen-Boden");
    6.         MeshFilter meshfilter = go.AddComponent(typeof(MeshFilter)) as MeshFilter;
    7.         MeshRenderer meshrenderer = go.AddComponent(typeof(MeshRenderer)) as MeshRenderer;
    8.  
    9.         Mesh mesh = new Mesh ();
    10.         mesh.vertices = new Vector3[]
    11.         {
    12.             new Vector3(0,0,0),
    13.             new Vector3(width,0,0),
    14.             new Vector3(width,0,depth),
    15.             new Vector3(0,0,depth),
    16.         };
    17.  
    18.         mesh.uv = new Vector2[]
    19.         {
    20.             new Vector2(0,0),
    21.             new Vector2(0,1),
    22.             new Vector2(1,1),
    23.             new Vector2(1,0)
    24.         };
    25.         mesh.triangles = new int[] { 0, 1, 2, 0, 2, 3 };
    26.         mesh.triangles = mesh.triangles.Reverse().ToArray();    //turns the mesh-visibility upside down!
    27.  
    28.  
    29.         meshfilter.mesh = mesh;
    30.         if (collider)
    31.         {
    32.             (go.AddComponent(typeof(MeshCollider)) as MeshCollider).sharedMesh = mesh;
    33.         }
    34.  
    35.         meshrenderer.material = material;
    36.         mesh.RecalculateBounds();
    37.         mesh.RecalculateNormals();
    38.  
    39.         return go;
    40.     }  
    41. }
     
  2. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    8,130
    You can't give it two textures without writing some sort of custom shader. What you could do instead is make two half-chessboards, one for the red squares and one for the black squares. Then you can give each one a separate texture.
     
  3. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,137
    Or use a texture atlas and set the UVs as appropriate.

    --Eric
     
    Joe-Censored, Ryiah and JoeStrout like this.
  4. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    8,130
    Quite right, that's certainly how I would do it. I may have taken the requirements in the question (using two separate textures) too literally.
     
  5. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,137
    There's also texture arrays, though that requires shader editing and doesn't work on older platforms, but then you don't have to worry about mipmaps/texture padding for atlases.

    --Eric
     
  6. Bill_Martini

    Bill_Martini

    Joined:
    Apr 19, 2016
    Posts:
    375
    I'd just use a single texture built in PS or Gimp using both images. I've done a user customizable board where you select two images from a group and the texture is created from those and applied to the plane. But still, just a single texture.
     
  7. romanpinkel

    romanpinkel

    Joined:
    Sep 4, 2019
    Posts:
    17
    I think I have to try the 1 combined texture because I spawned now 200*200 objects with each a different texture like a chess board but even if the textures are mono-colored I get high performance problems when walking / looking at those textures. (100x100 seems to run ok)
     
  8. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    8,130
    Hmm, 200x200 quads really shouldn't be a problem, if they're sharing textures. Check the rendering profiler to make sure you don't have more than a handful of draw calls. If you've somehow got a separate material for each square instead of sharing them, that'd certainly kill performance.
     
    Ryiah and Bill_Martini like this.
  9. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,137
    You could just make a single mesh that has all the squares.

    --Eric
     
    Ryiah and Bill_Martini like this.
  10. Bill_Martini

    Bill_Martini

    Joined:
    Apr 19, 2016
    Posts:
    375
    Normally I would say you shouldn't worry about performance this early, but you've already stated your having performance problems. So let's address tricks to improve that.

    You're spawning 40000 objects? Are all of them visible at the same time? Is this a voxel environment? Can your environment be built in Maya/Blender/Etc and use a single mesh in place of many objects? Combining meshes even if they have different textures, then using a texture atlas, can save a whole lot of draw calls. Can you replace multiple planes with a single one and make the texture suit the planes removed?

    Some easier stuff would be to mark every object that does not move as Static and make sure Occlusion is set. Create 2D art that look like the 3D objects and apply to a single plane or quad replacing 3D objects with an easy to render flat image. Look for ways to reduce the number of objects and textures used, game development is all about finding ways around issues, now is as good of a time as ever to start. Things aren'y always what they appear in games, the eye can be tricked quite easily. Get creative.

    Just because Unity allows you to build an environment with little or no outside assistance doesn't mean you should. 3D editing apps like Maya or Blender are generally used to do that and just import into Unity.
     
    Ryiah likes this.
  11. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    14,382
    That said you could very easily create a chessboard with ProBuilder.

     
    Bill_Martini likes this.
  12. Bill_Martini

    Bill_Martini

    Joined:
    Apr 19, 2016
    Posts:
    375
    Yes, ProBuilder is another option that I hadn't thought of.

    After my last post, I couldn't get over the 40000 planes, that's no chessboard! I'm assuming (since you said you were walking around on it) that you're just building a large ground tiled environment in a checkerboard pattern. If this is the case, you just need to build a few larger planes with your checkerboard texture applied. As you move away from one plane behind you, it is moved to in front of you. The trick is use ones from an unseen distance and place in an unseen distance (a little fog can help). You can use a minimum of 2x2 grid in your texture (upper right and lower left one image and upper left and lower right another), but I'd make them much bigger. Maybe 20x20, that would make each plane 100mx100m (using your 5m reference from above).

    Look at some video tutorials on endless runners. These only move environmental segments in a forward direction, but the principals are the same and can be adapted easily.

    Nothing is all good news though. As you wander farther away from origin (0,0,0) the math precision starts to suffer and things get glitchy. There are two ways to solve; Periodically reset everything back to origin, this is not noticeable as everything including the camera is kept relative to each other while moved as a whole. Or keep your player stationary (always at origin) and move the ground, this looks identical to moving over a stationary ground and is probably what you'll find being used in the endless runner tuts.

    I blabbed on a lot, I hope I'm correct one what you are doing.
     
    JoeStrout and Ryiah like this.
  13. Bill_Martini

    Bill_Martini

    Joined:
    Apr 19, 2016
    Posts:
    375
    And yet there is another, more simpler way...

    Make a single plane that stretches to the horizon in all four directions. Create a texture in the checkerboard pattern to suit your cell size requirements and apply to the plane. Now to move around, you don't move the player/camera or the ground, just scroll the uv's in the opposite direction you are facing. You should be able to do this in under an hour. Can't believe I didn't think of this first.
     
  14. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    8,130
    That's the right solution if you have correctly inferred what the OP is actually trying to accomplish. Unfortunately he didn't really tell us that; he asked a more specific question.

    I'm pointing this out just for the benefit of other newbies who might be lurking... it's always best to describe what you really want to accomplish, rather than focus on some detail of your current approach, which might not turn out to be the best approach at all.
     
    Bill_Martini and Ryiah like this.
  15. romanpinkel

    romanpinkel

    Joined:
    Sep 4, 2019
    Posts:
    17
    ok, let me explain a little more.
    Yes, it should look like a chessboard but the size of the plane can be chosen by the user.
    He can choose if the size is e.g. 10x10, 5x20 or 200x200. (minimum 5x5 up to 200x200).
    Then my script creates the amount of 1x1 blocks which are really unperformant.
    Lets have a look at the scripts:
    This part calls the function which creates the small parts:

    Code (CSharp):
    1. for (int x = 0; x < Variablen_Transport.X_Laenge; x++)
    2.         {
    3.             for (int z = 0; z < Variablen_Transport.Z_Laenge; z++)
    4.             {
    5.                 if ((x + z) % 2 == 0)
    6.                 {
    7.                     bodenBelag = bodenBelag01;   //defines the ground texture
    8.                 }
    9.                 else
    10.                 {
    11.                     bodenBelag = bodenBelag02;  //defines the ground texture
    12.                 }
    13.                 GameObject bodenStueckZuSpawnen = Create_Terrain_Helper_Dual.CreatePlaneDual(x, z, true, bodenBelag);
    14.                 bodenStueckZuSpawnen.transform.parent = GameObject.Find(nameDerBodensammlung).transform;
    15.             }
    16.         }
    the called function is:

    Code (CSharp):
    1. public static GameObject CreatePlaneDual (int position_X, int position_Z, bool collider, Material material)
    2.     {
    3.         CreatePlaneDual\" wird aufgerufen");
    4.         float position_Xf, position_Zf;
    5.         position_Xf = (float)position_X;
    6.         position_Zf = (float)position_Z;
    7.  
    8.         GameObject go = new GameObject("Boden (" + position_X + "/0/" + position_Z + ")");
    9.  
    10.         //Position festlegen
    11.         go.transform.position = new Vector3(position_Xf, 0, position_Zf);
    12.      
    13.         MeshFilter meshfilter = go.AddComponent(typeof(MeshFilter)) as MeshFilter;
    14.         MeshRenderer meshrenderer = go.AddComponent(typeof(MeshRenderer)) as MeshRenderer;
    15.  
    16.         Mesh mesh = new Mesh ();
    17.         mesh.vertices = new Vector3[]
    18.         {
    19.             new Vector3(0,0,0),
    20.             new Vector3(1,0,0),
    21.             new Vector3(1,0,1),
    22.             new Vector3(0,0,1),
    23.         };
    24.  
    25.         mesh.uv = new Vector2[]
    26.         {
    27.             new Vector2(0,0),
    28.             new Vector2(0,1),
    29.             new Vector2(1,1),
    30.             new Vector2(1,0)
    31.         };
    32.  
    33.         mesh.triangles = new int[] { 3, 2, 0, 2, 1, 0 };
    34.  
    35.         meshfilter.mesh = mesh;
    36.         if (collider)
    37.         {
    38.             (go.AddComponent(typeof(MeshCollider)) as MeshCollider).sharedMesh = mesh;
    39.         }
    40.  
    41.         meshrenderer.material = material;
    42.         mesh.RecalculateBounds();
    43.         mesh.RecalculateNormals();
    44.      
    45.         return go;
    46.     }
    perhaps Im doing something terribly wrong?
    If I create 1 single Plane with a repeating texture how can I assign the texture multiple times to it?
    atm Im using texture A and texture B, if I make a combined texture I would create a look like
    AB
    BA
    and apply it several times (hopefully a half one would be allowed).
     
  16. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    8,130
    You assign to material.mainTextureScale.

    And from what you've said you're trying to do, this is the right way to do it. Make a simple Plane with a 2x2 checkerboard texture, and then set mainTextureScale to make this repeat as needed.