Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Recreating board game track

Discussion in 'Scripting' started by GetUpKidAK, Nov 8, 2014.

  1. GetUpKidAK

    GetUpKidAK

    Joined:
    Apr 9, 2013
    Posts:
    84
    Hi,

    I've been hitting brick walls with an idea I've had for a while now so wanted to check if anyone could give me any ideas on where I might be going wrong.

    Basically, I'm looking to recreate a board game based on Formula One and I'm falling at the first hurdle when it comes to recreating the track, which for my early tests is this:



    I've managed to create the start-finish straight by essentially creating a rectangular grid of TrackPieces but it all falls apart on the corners.

    Even if I lose the black sections and stick with a fixed width (of 4 tiles) I've struggled with how to achieve the bends, so I'm just wondering if anyone has any suggestions as to how they'd go about recreating this?

    My main issues:
    - I've tried generating a mesh procedurally, but I'm not sure how I can get this mesh broken into tiles once it's done (as well as still struggling with the corners).
    - The grid idea is (was?) so I could obviously track the neighbours of each tile for movement, etc, but this breaks when the insides of the corners have pieces that span more than one normal tile length (see the first corner where the '40' section is three tile pieces long).

    Any help is *massively* appreciated!
     
  2. MrPriest

    MrPriest

    Joined:
    Mar 17, 2014
    Posts:
    202
    You are talking about the grid in a tile-based code kind of thing right?
    So why make it so complicated?
    How about "spreading" the board as one straight long track to create the grid?
    Visual representation does not have to look like the code, you know.

    As for the corners, like where there is that 40, use data that says "wall" or something, so the code knows that there is no one on the left, because there's a wall thing there.

    [r][r][r][r][r]
    [\u][w][w][w][r]
    [r][r][r][r][r]
    [r][r][r][r][r]
    r = road
    w = wall
    u = un-used (since the roads merged, this tile is un-used, or something like that)
     
    Last edited: Nov 9, 2014
  3. GetUpKidAK

    GetUpKidAK

    Joined:
    Apr 9, 2013
    Posts:
    84
    Sorry, I was probably a bit vague in my request.

    Creating a grid that, in code at least, goes from start to finish as if it's a straight line isn't an issue, the problem is more about how I connect that to the visual side so that the player interaction works.

    I wrote the following to generate a mesh and a gameobject for each 'tile' that would be used for the gameplay aspects, but I've had issues generated a curved mesh that put an end to it.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections.Generic;
    3.  
    4. [RequireComponent (typeof (MeshFilter))]
    5. [RequireComponent (typeof (MeshRenderer))]
    6. [RequireComponent (typeof (MeshCollider))]
    7.  
    8. [ExecuteInEditMode]
    9. public class TrackGen : MonoBehaviour
    10. {
    11.     public float tileWidth = 1.5f;
    12.     public float tileLength = 2.5f;
    13.  
    14.     public int gridWidth = 4;
    15.     public int gridLength = 15;
    16.  
    17.     Mesh mesh;
    18.     MeshFilter filter;
    19.     MeshCollider col;
    20.  
    21.     List<Vector3> verts = new List<Vector3>();
    22.     List<Vector2> uvs = new List<Vector2>();
    23.     List<int> tris = new List<int>();
    24.  
    25.  
    26.     // --- Monobehaviours --- //
    27.  
    28.     void Start()
    29.     {
    30.         filter = GetComponent<MeshFilter>();
    31.         col = GetComponent<MeshCollider>();
    32.      
    33.         mesh = new Mesh();
    34.         mesh.name = "Grid";
    35.  
    36.         GenerateMesh();
    37.     }
    38.  
    39.  
    40.     // --- Public class functions --- //
    41.  
    42.     public void GenerateMesh()
    43.     {
    44.         GenerateVerts();
    45.         AddTriangles();
    46.      
    47.         mesh.Clear();
    48.      
    49.         mesh.vertices = verts.ToArray();
    50.         mesh.triangles = tris.ToArray();
    51.         mesh.uv = uvs.ToArray();
    52.      
    53.         mesh.Optimize();
    54.         mesh.RecalculateBounds();
    55.         mesh.RecalculateNormals();
    56.      
    57.         filter.sharedMesh = mesh;
    58.         col.sharedMesh = mesh;
    59.      
    60.         // Hack to force collider to update
    61.         col.convex = true;
    62.         col.convex = false;
    63.      
    64.         Debug.Log("Mesh Generated. " + verts.Count + " vertices, " + (tris.Count / 3) + " triangles.");
    65.  
    66.         // TEMP HACK FOR POSITIONING
    67.         float meshWidth = (tileWidth * gridWidth) * 0.5f;
    68.         transform.position = new Vector3(0 - meshWidth, 0f, 0f);
    69.      
    70.         CreateTileObjects();
    71.     }
    72.  
    73.  
    74.     // --- Class functions --- //
    75.  
    76.     void GenerateVerts()
    77.     {
    78.         // Clear lists before reassigning
    79.         verts.Clear();
    80.         uvs.Clear();
    81.  
    82.         for ( int z = 0; z <= gridLength; z++ )
    83.         {
    84.             for ( int x = 0; x <= gridWidth; x++ )
    85.             {
    86.                 // Vertices
    87.                 Vector3 vertPos = new Vector3(x * tileWidth, 0f, z * tileLength);
    88.                 verts.Add(vertPos);
    89.  
    90.                 // UVs
    91.                 Vector2 uvPos = new Vector2(x, z);
    92.                 uvs.Add(uvPos);
    93.             }
    94.         }
    95.     }
    96.  
    97.     void AddTriangles()
    98.     {
    99.         // Clear before reassigning
    100.         tris.Clear();
    101.  
    102.         int vertsPerRow = gridWidth + 1;
    103.  
    104.         for ( int z = 0; z < gridLength; z++ )
    105.         {
    106.             for ( int x = 0; x < gridWidth; x++ )
    107.             {
    108.                 int tri0 = x + (z * vertsPerRow);
    109.                 int tri1 = x + vertsPerRow + (z * vertsPerRow);
    110.                 int tri2 = x + vertsPerRow + 1 + (z * vertsPerRow);
    111.                 int tri3 = x + 1 + (z * vertsPerRow);
    112.  
    113.                 tris.Add(tri0);
    114.                 tris.Add(tri1);
    115.                 tris.Add(tri2);
    116.                 tris.Add(tri0);
    117.                 tris.Add(tri2);
    118.                 tris.Add(tri3);
    119.             }
    120.         }
    121.     }
    122.  
    123.     void CreateTileObjects()
    124.     {
    125.         // Clear existing objects if mesh is updated
    126.         if (transform.childCount > 0)
    127.         {
    128.             List<Transform> children = new List<Transform>();
    129.  
    130.             for ( int i = 0; i < transform.childCount; i++ )
    131.             {
    132.                 Transform child = transform.GetChild(i);
    133.  
    134.                 children.Add(child);
    135.             }
    136.             foreach (Transform child in children)
    137.             {
    138.                 DestroyImmediate(child.gameObject);
    139.             }
    140.             children.Clear();
    141.         }
    142.  
    143.         for ( int z = 0; z < gridLength; z++ )
    144.         {
    145.             for ( int x = 0; x < gridWidth; x++ )
    146.             {
    147.                 GameObject go = new GameObject(x + ", " + z);
    148.                 go.transform.position = new Vector3(x * tileWidth + (tileWidth * 0.5f), 0f, z * tileLength + (tileLength * 0.5f));
    149.                 go.transform.parent = this.transform;
    150.             }
    151.         }
    152.     }
    153. }
    154.  
    As I said before, I also tried to take a pre-built mesh and split it, manually, into gameobjects that would represent each gameplay 'tile', but the issue was that eventually the row numbering would break (after corners like I mentioned before) and I'd need some long-winded logic to check for tiles that have more than one neighbour to one side.

    My guess would be that I need to generate the grid as evenly spaced tiled all the way around but find a way of telling some tiles to merge with nearby tiles where I need longer pieces. I think!
     
  4. MrPriest

    MrPriest

    Joined:
    Mar 17, 2014
    Posts:
    202
    I figured what you've asked could not have been about what I've said, but I wanted to make sure.
    I still do not quite understand the issue, however...
    But I am also not that experienced with mesh-generation, yet.
    Good luck.