Search Unity

Collision checks on dynamically created meshes

Discussion in '2D' started by steg90, Dec 18, 2017.

  1. steg90

    steg90

    Joined:
    Jan 26, 2016
    Posts:
    93
    Hi,

    I've created dynamic gameobjects (mesh) which hold 10x10 quads in each of them, think of the game object as a chunk.

    What I want to know is how you can attach collision checks to each of these quads? These quads will represent walls/cave cells player cannot move through, think of terraria, this is what I'm trying to create.

    So each game object has 100x100 quads, each quad has an associated texture coordinate. The game objects are attached to a main blank game object. I've obviously created the game objects this way so I can have a very large world using less than 50 game objects.

    Can I use colliders or should I just roll my own collision checks? Please see image attached which shows 2 game objects, each has 100 quads, I just roll a random value to see if I create a quad or not (this will change to cellular automata).

    Any help is much appreciated.
     

    Attached Files:

    • cave.PNG
      cave.PNG
      File size:
      18.8 KB
      Views:
      914
  2. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    You should absolutely, definitely, certainly run your own collision checks. Your world is a grid; it is much, much easier (and more efficient) for you to simply look up data about that grid than to ask the physics engine (which has no knowledge of the grid-like nature of your world) to do it.

    But yes, if you really want to do things the inefficient way, you can attach a collider to each of your quads at runtime.
     
  3. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Also, I'm not sure what you mean by this. 100x100 quads is 10,000 game objects. The fact that you stick them inside another blank game object doesn't mean they are 1 object; in means you now have 10,001 game objects.

    The proper way to do what you're doing is to create one mesh for as much of the world as can be seen at once, and dynamically update its UV coordinates to reflect the contents of the world in front of the camera. This is fairly advanced stuff, so you might want to consider using a solution from the Asset Store, or the new Tile stuff that Unity recently added (I see they have some tutorials about it in the Learn section, though I haven't yet played with this myself).
     
  4. steg90

    steg90

    Joined:
    Jan 26, 2016
    Posts:
    93
    Hi,

    Thanks for that, I have one big mesh per chunk (400 quads per chunk in example shown in attached image). I've attached another image to clarify, it shows 16 chunks which creates 16 game objects.

    Yes, I thought as much that the colliders would cause issue using unities due to overhead of this.

    I could check where player is in relation to quads - but say player is at position 200,100, how do I determine if this is a block/quad? So for example, if I have a method:

    bool isBlock(float x, float y) {
    // <---- How to determine what to check - quads are stored in game object
    }

    Would you suggest storing all the quads in an array?

    Not looked at the new tiled stuff in unity, not sure if it allows for 'unlimited' tiles?

    Thanks
     

    Attached Files:

    • cave.PNG
      cave.PNG
      File size:
      379.4 KB
      Views:
      822
    Last edited: Dec 18, 2017
  5. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Yes, you should simply have a 2D array of enums or small structs or whatever, that keep track of what's in the world.
     
  6. steg90

    steg90

    Joined:
    Jan 26, 2016
    Posts:
    93
    If the world was say 2 million tiles, that would be a very big array, is there a more efficient way? Be nice if could attach an object to each quad...
     
  7. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    The array size is trivial compared to all the data already associated with those tiles. Don't worry about it.

    (Unless your world is mostly empty space, and you want to use something like a spare matrix... but do that only after determining that it's actually an issue.)
     
  8. steg90

    steg90

    Joined:
    Jan 26, 2016
    Posts:
    93
    Thanks again,

    I've just used a 1D char array to store each quad.

    Issue with collision though would be the blocks/tiles would pretty much have to be square shape as not using any physics...
     
    Last edited: Dec 19, 2017
    JoeStrout likes this.
  9. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    As you wish. But a 2D array would be the same amount of memory, and slightly faster to use.

    That depends on the code you write — you certainly could handle slopes etc. if you want to.
     
  10. steg90

    steg90

    Joined:
    Jan 26, 2016
    Posts:
    93
    Will need to look at some tutorial to handle slopes :)

    On another note, looking at creating something like Downwell to get me more experience using Unity, I think using what I've done could be a good way of doing something similar, can just have one chunk wide but many chunks deep, all created proceduraly.
     

    Attached Files:

    Last edited: Dec 19, 2017
    JoeStrout likes this.
  11. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    I haven't seen Downwell, but from the screen shot, it looks similar in some ways to Rocket Plume (which was created with PixelSurface).
     
  12. steg90

    steg90

    Joined:
    Jan 26, 2016
    Posts:
    93
    Hi Joe,

    Downwell was created with GameMaker and does look like Rocket Plume, I see you wrote that :) I have a son who is 14 and he sometimes does artwork for me. I've been coding for 22 years, mainly C++,Java, Javascript and C#. Used Unity on and off but want to start using it seriously now (I've used LibGdx, Unreal engine, vanilla Direct3D/X, OpenGL in the past).

    I've got the player falling down the screen now with the map scrolling up, I wrote some code to make the main camera following the players Y position. I'm just wondering if checking position of player to 'tile/quad' for collision would work with the camera moving down screen quite quick or would player sometimes go through the 'platforms'?...
     
  13. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    If your player is moving more than 1 tile height per frame, then yeah, he could pass through a 1-tile-high obstacle unless you've written your code to account for it.

    Just iterate, in tile-sized steps, between where the player was previously, and where you want to put him on this new frame, and check the grid for each position in between. You can easily do that iteration with Vector2.MoveTowards.
     
  14. steg90

    steg90

    Joined:
    Jan 26, 2016
    Posts:
    93
    I move the player object in the update method as follows:

    Code (csharp):
    1.  
    2.         float hrz = Input.GetAxisRaw("Horizontal");
    3.         transform.Translate(hrz * Time.deltaTime * 2.0f, -1f * Time.deltaTime * 3.0f, 0);
    4.  
    Then in the camera gameobjects update:
    Code (csharp):
    1.  
    2.         GameObject player = GameObject.FindGameObjectWithTag("Player");
    3.         if(player!=null)
    4.         {
    5.             Vector3 pos = player.transform.position;
    6.             pos.y -= 1f; // so player is a little higher up the screen
    7.             Camera.main.transform.position = new Vector3(1.60f, pos.y, -100);
    8.         }
    9.  
    I haven't used MoveTowards before...so not sure how it would work but guess you give it a target vector and it moves to this at a given speed.

    If I was to add colliders to the quads dynamically, how would this be achieved as the quads aren't game objects?...

    Part of the code that generates my quads:
    Code (csharp):
    1.  
    2.                        
    3.        newVertices.Add(new Vector3(x / d, y / d, 0));
    4.        newVertices.Add(new Vector3(x / d + width, y / d, 0));
    5.        newVertices.Add(new Vector3(x / d + width, y / d - height, 0));
    6.        newVertices.Add(new Vector3(x / d, y / d - height, 0));
    7.        // uvs
    8.        uvs.Add(new Vector2(0.0625f * (tileno - 1f), 0));  
    9.        uvs.Add(new Vector2(0.0625f * tileno, 0));  
    10.        uvs.Add(new Vector2(0.0625f * tileno, 1f));
    11.        uvs.Add(new Vector2(0.0625f * (tileno - 1f), 1f));  
    12.        // Create triangle indices
    13.         newTriangles.AddRange(new int[]
    14.         {
    15.                             0+count, 1+count, 3+count,
    16.                             1 +count, 2+count, 3+count
    17.         });
    18.  
    I can't see how I could add colliders unless each quad is a gameobject...
     
    Last edited: Dec 21, 2017
  15. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    You don't add colliders. You just do a bit of math to figure out which grid cell any point of interest is in, and look up in your array what sort of block is in that cell.
     
  16. steg90

    steg90

    Joined:
    Jan 26, 2016
    Posts:
    93
    Yes that was what I was going to do, but just wondered if it would have been possible to use colliders.

    Was going to convert player x,y position to the chunk/quads array position.
     
  17. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Yes, it's possible to use colliders, but I really don't recommend that — not only is it harder, but it will also perform much, much worse.

    When you have a gridlike world, you should take advantage of that (which the physics engine can't do).
     
  18. steg90

    steg90

    Joined:
    Jan 26, 2016
    Posts:
    93
    Trying to work out how to create the procedural wall - please see here

    Just wondering if unity is the tool to use for this sort of game?...
     
  19. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Yes, Unity is a fine tool for this sort of game. I can think of at least three ways to do it, all of which would work fine:
    1. Use PixelSurface, predrawing the map at level load time. This would let you chew through rocks in arbitrary ways, rather than only by grid cells. But if you don't need to do that, then this approach is probably overkill.
    2. Use a tile engine, or make your own, which creates a single mesh for the level (or the portion of it visible on screen) in the shape of the grid, and updates the UV coordinates to draw the appropriate tiles.
    3. If it really is like the video shown, you probably could just do it all with sprites — I don't see more than a few dozen sprites on screen at a time. But you would probably want to create the sprites just in time as the camera moves down, and recycle them when they go off the screen at the top, so you don't have hundreds (or thousands) of sprites in the scene at once.
     
  20. steg90

    steg90

    Joined:
    Jan 26, 2016
    Posts:
    93
    Thanks for that.

    I'm still doing it the way where I dynamically create chunks of meshes at the start, the chunks contain random platforms now created out of quads. The Downwell game was written using GameMaker, I've got a license for desktop version of that but the mobile phone deployment is expensive to purchase, I would imagine doing this sort of game in GameMaker is a lot easier than doing it in Unity but would be limited.

    Not sure about moving the UV coordinates, I can see this would allow just one mesh the size of the screen.

    Using sprites, how would you create the whole level dynamically using these?
     
  21. steg90

    steg90

    Joined:
    Jan 26, 2016
    Posts:
    93
    Hi,
    Any chance you could have a quick look of what I've got so far?
    Here is a drop box link:Falling

    When you run it if you do it will go blank for a small time as the map is generated (about 10 seconds on my laptop but I've got a 1050ti and i7).

    No collision in the game, normal keys to move A and D, spacebar will zoom map out and R to reset. As you will be able to see, the map is huge, the player pos in top left of screen shows where player is, starts at 1600 and 0 is end of map which will take a while to get to.

    As you can see the platforms aren't that great, best I could do at the moment, they are randomly generated at the start of the game from the left and from the right of certain position and length.

    Thanks