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

C# Grid Based Map question

Discussion in 'Scripting' started by AllanMSmith, May 17, 2018.

  1. AllanMSmith

    AllanMSmith

    Joined:
    Oct 2, 2012
    Posts:
    180
    Hey,

    So, I am developing a strategy game which has a grid of nodes, described by a list of nodes. Nodes have references to their neighbors and I've already have systems in there like basic pathfinding, road building and so on. However, I just started creating the system to build stuff, the caveat being that buildings can be larger than 1 tile (unlike roads which connect with other nearby roads but are just 1 tile in size).

    The question is... what is the best way to do that? I mean, what I am doing right now is, choosing the X tiles the building will occupy (say 9 tiles), setting them all to have a reference to this building, and instantiating the building prefab in the center tile. This works, and seems like a good enough solution, but I am serializing the most barebones I can of this so I can recreate the world from a pre-set state (saving a json), and idk, but it feels I might be doing something wrong here. This is making it hard for me for stuff like rotating the building (rotating is easy, but the building has entrance and exit points and rotating those among the 9 selected tiles is going to prove not trivial), and idk, the linking between the nodes is... weak, is index based... so say this 9 tile building, at time of construction it will store a tile index in each tile, so if I click on tile 9, I have a way to calculate what are the other 8 tiles... but idk.

    Anyone knows some good resources on ways to approach this problem? This has been done thousands of time already in the history of gaming but I couldnt find anything about this specific question... so any references would be super helpful!

    As a ps, I do have some years making games so Im not the noobest there is, this is actually a deterministic multiplayer game and I got that going so I feel like I am struggling with a part that should be easy haha but is proving a bit of harder than expected.

    Anyway, thanks for the attention!
    Best,
    Allan
     
  2. aer0ace

    aer0ace

    Joined:
    May 11, 2012
    Posts:
    1,513
    Why do I feel like it's me asking this very same question? I also have a tile-based game, and will eventually need to handle the case of the same unit/entity/actor on multiple tiles (so far, only one "unit" per tile). I think with the questions you ask and the suggestions that you're giving yourself, you already have a good idea of how you're going to do it.

    You've described sort of how I'm going to approach it. I wanted to support the general case, and not the uniform case, where the unit position is directly in the center, and it supports only odd-by-odd sizes. That's kind of uninteresting, but I'll probably end up going that route, finding that the general case is way too hard to support, but who knows.

    For the general case, a multi-tile unit will indicate that it first occupies the "origin" tile, where the position of the object is. The unit then has to have knowledge of what tiles it would occupy in the untransformed case. Then, based on unit rotations, transform those tile occupations accordingly. For my grid, each tile has a pointer to the unit that's occupying it. And each unit does NOT have a pointer to the tile that it occupies. That is determined simply by position in the world and then querying the grid for the tile based on that position. I will most likely continue that paradigm and extend it to support the multi-tile case as mentioned above.

    I like these sorts of discussions =). Although not Unity-specific, I hope it helps a lot of people.


    EDIT:
    I wanted to add more regarding entry and exit points on the building. Those are key locations on the building, and are definitely important positions, so those need to be stored in the untransformed state, typically called "model space". When the building is transformed, the entry/exit points have to be transformed about the pivot point of the building. Then, you can determine the new location of the entry/exit by querying the grid, just like I mentioned above.
     
    Last edited: May 17, 2018
  3. AllanMSmith

    AllanMSmith

    Joined:
    Oct 2, 2012
    Posts:
    180
    Thanks for the input @aer0ace !

    Yeah looks like we are going somewhat in the same direction. It definitely is not unity specific at all, to be honest I am developing almost everything in a completely unity independent way... not because I plan on using another engine but because I want control over it... and I need determinism which means I am refraining from using floats (at all, the actual logic is all done in ints atm).

    I get what you are saying about querying the world, but this is something I am trying to do as little as possible. Even though I have a pretty fast querying code in place, its still not the lightest of operations and if I can avoid it, I prefer to do so. So my idea is pretty much what you just said, tiles know whats on top of them, multiple tiles are pointing to the same structure, the structure on the other hand does NOT know which tiles it is on, it just knows "structure specific stuff" (say health or whatever). Since the structure itself is not a monobehaviour for me, it doesnt even have a position (I might have to add it at some point), its just data.

    I do have those points saved in a default manner (entrance point, exit point), but the actual rotating of those points... well I still havent tried but im not sure how I will go about it. Since its all data, all logical, there is no game object to rely on... I dont know how I will go about the "math"... I mean, take this as an example:

    X X X
    E X O
    X X X

    Considering E = entrance, O = out, and that tiles, in my scenario, would be numbered like this:

    2 5 8
    1 4 7
    0 3 6

    Obviously if I rotate it clockwise, entrance would be tile 5 and exit tile 3.... but, the math to get to that haha idk yet how the hell im going to do that and If I could refrain from hard coding it to 4 possible states and picking the right one (even though thats doable) I would prefer to do so. But then again, what is bothering me right now is the "serializing" part. So far, with roads and stuff... I've been able to serialize the world into a very neat little json, I dont have to serialize connections or basically anything for that matter... I just have to serialize "this tile has a road on it" and when the world is rebuilt, I just re-create the connections at run time... but for this kind of building... im still not sure how to serialize it... I mean, I have 9 tiles pointing to 1 structure... I need to save the structure itself, and have the 9 tiles pointing to it... as I am writing though haha, might be that I have to do some SQL style referencing... just IDing the structure and putting an id into the tiles that links both together... so I just have to serialize the structure once in some kind of structure array and the tiles just point to the structures they contain through id...

    See, I know asking and writing about it would help clear my mind =P

    Btw it is important for me that the serialization is super barebones for size of json, bandwith, simplicity... as is determinism and network messages being as small as possible... so as much as I can transform ultra simple data into more complex stuff at runtime... it does make a difference for my specific project.
     
  4. aer0ace

    aer0ace

    Joined:
    May 11, 2012
    Posts:
    1,513
    Are you familiar with matrix rotation and trigonometry?
    I'll refresh generally speaking just for a starting off point.
    Rotation can be expressed from 0 to 360 degrees, or 0 to 2PI.
    We use sine and cosine to determine that point.
    Typically
    x = r*cos(angle)
    y = r*sin(angle)

    That's the principle. But, I'm going to make an assumption, that you are rotating on 90 degree increments only. If that assumption is incorrect, then disregard this trick, but the trick is fabulous for orthogonal rotations.

    Observe that for:
    sine, you get the value of 0, 1, 0, -1 for angles 0, 90, 180, 270
    cosine, you get the value of 1, 0, -1, 0 for angles 0, 90, 180, 270

    Since you're dealing with integers, if you rotate every 90 degrees, this is essentially choosing one of four quantized possibilities.
    So, you can create a map of angle to sine/cosine pair, and use that to multiply your x,y coordinate to rotate it.

    Hope this helps.
     
  5. AllanMSmith

    AllanMSmith

    Joined:
    Oct 2, 2012
    Posts:
    180
    Thanks @aer0ace , that does help!

    So let me see if I got this straight. Currently, I have the building position, and then those entrance/exit points are relative positions. So for example, I got this building at 10, 10 position:

    X X X X X X
    X X X X X X
    X X X X X X
    X X X X X X
    X X X X X X
    X X X X E X

    This means E is at 2, -3 relative position. If I rotate it 90 degrees, I want E position to be 3, -2:


    X X X X X X
    X X X X X E
    X X X X X X
    X X X X X X
    X X X X X X
    X X X X X X

    Now... your assumption is right, Im always rotating 90 degrees, but still not clear how to use sin/cos to get to that result. I will try to think of something when I get home as I havent given this much thought yet, but how would that trick apply here?

    Best,
    Allan
     
  6. AllanMSmith

    AllanMSmith

    Joined:
    Oct 2, 2012
    Posts:
    180