I have a game that has an infinite world of hexagons. Obviously, I can’t spawn them all at once when the game starts, so I’m trying to figure out how to make a script that makes them tessellate perfectly as the player moves, and preventing any empty screen space. However, I’m not sure how to go about doing this. Any ideas? Each hexagon is the size of exactly 2 square units.
You can instantiate a hexagon at player position each x seconds, just save it as a prefab, but im not sure of having understand it at all, so, just an idea
Thanks for your reply! However, the problem with your idea is that the player is not always going to be on round numbers, so hexagons would overlap and not tesselate properly. The method I am trying to implement right now is storing 6 empty GameObject
s within the hexagon prefab, which contains the locations of imaginary neighboring hexagons. Then, it would check whether each of those points is in Camera.main
’s field of view and if there is isn’t a hexagon there already. If both are true, it clones itself at that location. However, at the moment that system is still buggy and needs a lot of work. I’ll keep this thread posted if I make any progress!
Well, I’ve got good news and I’ve got bad news. I managed to get the code to work, but it is sluggish as hell. Running it once takes around 1 second, which is pretty bad considering I need this to activate once every frame. This is what I’ve got, using the system I’ve mentioned earlier:
public void Spawn () {
List<Transform> blackList = new List<Transform>();
foreach (Transform spawn in spawns) {
if (!hexagonManager.CheckPosition(spawn.position)) {
Vector3 viewportPosition = Camera.main.WorldToViewportPoint(spawn.position);
if (Vector3.Distance(spawn.position, player.transform.position) < 20) {
Instantiate(gameObject, spawn.position, Quaternion.identity, null);
blackList.Add(spawn);
}
} else {
blackList.Add(spawn);
}
}
foreach (Transform spawn in blackList) {
spawns.Remove(spawn);
Destroy(spawn.gameObject);
}
}
You could “buffer” your hexagons in chunks.
Create a chunk prefab (say 20x20 units in size => 10x10 hexagons) and have each chunk check whether or not it is fully contained within the viewport. To do that you can use simple points - create a vector 2 for each top-left and top-right and use WorldToViewportPoint to check if the viewport rectangle is fully contained within your chunk; if not, generate the appropriate chunks needed.
You can easily define a “chunk center distance” to avoid hexagons overlapping.
I was thinking about using the chunk method, but I wanted to try the hexagon-by-hexagon method first. However, now that I know that that method is completely impractical, I’ll use the chunk method as you suggested. Thanks so much for your response; I’ll keep this thread posted if I make any progress!
If you really wanted to do hexagon-by-hexagon a solution would be to make the existing hexagons responsible for spawning new ones.
Say a hexagon “notices” that it is getting too far away from the screen edge, it then instantiates another hexagon next to itself. In order to prevent performance issues you would need to find a way to only check the hexagons that are 1) at the edge and 2) visible (or close to visible)
Grr… I’m not sure what I’m doing wrong here. I’ve got a very simple spawning script and it is still taking approximately 1 second per spawn to work. No lists, no hexagon-by-hexagon spawning… just clusters of approximately 40 hexagons in 10 by 10 unit sections. Could Vector3.Distance
somehow be sapping all of the resources? I tried disabling all of the scripts on the hexagons themselves, perhaps their Start
code was doing something, but nope. That didn’t work either. Any ideas?
void Start () {
Spawn(Vector3.zero);
}
void Spawn (Vector3 offset) {
currentBlockPosition += offset;
Instantiate(block, currentBlockPosition, Quaternion.identity, null);
}
// Update is called once per frame
void Update () {
if (Vector3.Distance(transform.position, currentBlockPosition + upSpawn) < 5) {
Spawn(upSpawn);
}
if (Vector3.Distance(transform.position, currentBlockPosition + downSpawn) < 5) {
Spawn(downSpawn);
}
if (Vector3.Distance(transform.position, currentBlockPosition + leftSpawn) < 5) {
Spawn(leftSpawn);
}
if (Vector3.Distance(transform.position, currentBlockPosition + rightSpawn) < 5) {
Spawn(rightSpawn);
}
}
I finally figured it out. There was an Animator
component on each hexagon, which stopped the lag as soon as I removed it, but the question remains… why is Animator
an issue?