For a project I'm remaking Minecraft's voxel blocky terran.
Currently im using a 3 key array(new Block[,,]) and then i can reference a block using its cords like BlockList[x,y,z].BlockID and stuff like that.
But i want infinite terrain which isn't possible with a array. So would a List be better for this?
Keep in mind there are ~200k blocks loaded at any given time - I am
afraid of looping through each block in the list to find the block
requested would be heavy on CPU.
Related
I'm coding a 2d tile-based, turn-based game in Unity, and have been struggling to solve a problem for the past two days. At first, I managed to get tile to tile pathfinding working using the Dijkstra algorithm. Next, I tried modifying the code to instead efficiently pathfind to every tile within a character’s movement range
To that end, I’m trying to make a method that returns a dictionary. The keys are all the reachable WorldTile tiles within the character’s mobility range (WorldTile is a class representing each tile in the game) and the value for each key is a PathAndCost pathAndCost (PathAndCost is a class that stores 2 properties: Path, of type Queue and Cost, of type Double).
This way, I can store a list of all the tiles the character can reach while simultaneously also storing the path to each tile (represented by a Queue of tiles) and the cost to reach each tile (represented by a Double).
However, in practice, there is something wrong with the method and I can’t figure out what exactly is wrong. Through testing, I’ve confirmed that the dictionary that the method returns DOES correctly contain all the reachable tiles as its keys. Meanwhile, the pathAndCost values returned are only half correct. Strangely, each pathAndCost.Cost is correct. However, pathAndCost.Path is always wrong. When I check the queue count of the paths being stored, it’s always 0, meaning no tiles are stored in the paths!
github link to my script
(apologies if formatting of my post or code is messy as I am new to both stackoverflow and programming)
If you look at the two Debugging blocks I wrote in my script, INSIDE the StorePathAndCost loop, the paths are indeed being made correctly as queue counts there are not always 0. Somehow, something goes wrong afterwards that sets the paths back to being empty before the method returns the dictionary.
Since the tile keys and cost values aren’t being affected, I highly suspect that there is a logical error in the way I’m making and storing the paths within the StorePathAndCost loop. I’ve stared at my code for so long and can’t figure out what it is though.
EDIT: Solved! Realised that the problem lies in the Dequeue() method affecting my path values even after they were stored in the dictionary.
Not going to wade through your whole program code, but I will offer help in the form a nice video tutorial showing a successful way of implementing pathfinding for ya.
Tarodevs Pathfinding
Let's say i have a fairly large 2D array (a bit over 2 million entries) containing some basic objects (in my case, it's a 2d array of pixel objects).
My goal is to loop through every item in the 2D array and do some basic modification to the object, such as changing one of its properties or something.
Currently i am just looping through it with a foreach and accessing each object via the loop.
This takes around 2 seconds to accomplish with C#.
I am wondering if there is a faster way for me to accomplish this. I wrote some similar code in c++ a long time ago and it performed almost instantaneously, so i'm a bit disappointed that performance has suffered a bit in C#.
Can i somehow speed things up with asynchronous code perhaps? Am i doing something in a less-than-optimal way?
foreach (Pixel p in my2Darray.Pixels) //this is a 2d array but we can still just loop through it with a single for loop
{
p.SetColor(Color.red);
}
I've a question on how to optimize a triple for loop which would grant me a huge performance boost.
Let's say I've a chunk of 16x16x16 blocks, so we're talking 3D. I am currently looping every block in the chunk so I have three nested for loops. The thing is I only need the exterior part of the chunk to be iterated over if all blocks in it are rendered. If they are rendered I stop to check blocks for this particular chunk. If they are not all rendered, I do the same operation but for size-2 until size < 2. That would be the perfect way since it would only lookup the parts I need.
To compare iterations, if all blocks of the exterior in a 16x16x16 chunks are rendered that would give us 16^3 - 14^3 = 4096 - 2744 = 1352 blocks to check instead of 4096.
The only way I could think about is create different section for the chunk, so I would check the top part, then the left part, etc.
Thanks for reading
Edit :
Imagine something like this where the cubes are empty. Only the outter part is checked (I don't need help on the checking part. I just don't want to loop the inner part of the cube if the outside is alredy fully rendered)
I need a fast collection that maps 2D int-typed point to custom class in C#.
The collection needs to have:
Fast lookup (coords to custom class), adding a point if it does not exist
Fast remove range of key-point (outside of given rect). This actually rules out Dictionary<Point2D, ...>, as profiling found out this op is taking 35% of entire frame time in my sample implementation :-(
EDIT: To stress out: I want to remove all fields OUTSIDE of given rect (kill unused cache)
The coordinates can take any int-values (they are used to cache [almost] infinite isometric 2D map tiles that are near camera in Unity).
The points will be always organized in rect-like structure (I can relax this requirement to always follow rect, actually I am using isometric projection).
The structure itself is used for caching tile-specific data (like tile-transitions)
EDIT: Updated with outcome of discussion
You can use a sparse, static matrix for each "Chunk" in the cache and a cursor to represent the current viewport. You can then either use modulus math or a Quad tree to access each chunk, depending on the specific use case.
Old Answer:
If they are uniformly spaced, they why do you need to hash at all? You could just use a matrix of objects with NULL where is the default value if nothing is cached there.
Since you are using objects, the array is actually just references under the hood, the memory footprint of the array wouldn't really be affected by the null values.
If you truly need it to be infinite, you nest the matrices with a Quad Tree and create some kind of "Chunk" system.
I think this is what you need: RTree
I am creating large scale worlds using 16*16*16 voxel chunks which are stacked up to 32*32*32 in dimensions and I have hit a bit of a Bump in the road so to speak.
I want to create large structures that span 20+*20+*20+ chunks in volume which are created from procedurally generated structures as well as using templates for some of the content. Now I have an issue. The visual render range is up to 32*32*32 chunks and while I have up to maybe 40*40*40 chunks held in memory at a time when possible.
The structures can be anything like towns, dungeons and roads. I was thinking something like perlin worms for roads and just lay them over the terrain in the x,z and then analyze the path for bridges etc..
The structures and collection of structures need to be pre-generated before the player is within visual range or work more like perlin noise does for heightmaps (best solution). (to avoid the players seeing the generator at work). They also need to be consistent with the world seed every time.
I have thought about this a bit and have 2 possible solutions.
1) Generate the structures based on a point of origin for the structure generator.
This causes several issues though as even if I generate from the center of the structure, the structures can easily cross into the potential visual range of the player.
2) Pre-Generate "unreachable" chunks and then page them in and out in order to generate the structures using the above method.
This also seems rather unnecessary.
Both methods need to analyze the terrain in large quantities for a valid location to spawn the structures.
I was hoping somebody might have a more organic solution or even just a simpler solution that doesn't require me to "Look" so far ahead.
Thank you in advance.
EDIT:
I had an idea for dungeon generation in which I generate point clouds/nodes for rooms.
Steps:
1) When the generator finds a "node" it creates an x, y and z size to create a box basing it from the originator point of the room** (centre or corner of the room) and the room type.
**x,y,z relative to 0,0,0 worldspace calculated like so new Vector3((chunkX*16)+voxelX,(chunkY*16)+voxelY,(chunkZ*16)+voxelZ)
2) Once a room size is calculated, check for overlaps and if one is found do one of several things.
If the room overlap is high up lower it down till either the roof or the floor are flush. If the roof is flush build a stairs up to the room and remove the walls that intersect.
3) Look Down, North and East for a room maybe with a small cone and attempt to create a hallway between them.
This would probably work somewhat, especially if the center of the dungeon is the main hall/boss room.
This would be different for towns, cities, and surface dungeons. Still seems a little choppy though. Any ideas?
I faced a similar problem for a Minecraft mod I am writing. I want to have a number of overlapping "empires" which each create structures. But I don't want the structures to step on each other.
So, for this, I broke the world into arbitrary sized tiles. (Compare to your 32x32x32 regions.) I also came up with a "radius of influence". This is how far from the center point that it could create structures. Each tile had an instance of a provider class assigned to it with a unique seed.
Two methods on this class were provided for structure generation.
First, was a function that would return where it wanted to create structures. But only to the resolution of chunks. (Compare to your 16x16x16 block sets.) Each provider class instance had a priority, so in the case of two providers trying to rezz a structure in the same chunks, the higher priority one would win.
The second function would be passed a world instance, and one of the data items returned by the first function and would be asked to actually create it.
Everything pieces together like this:
We get a request to resolve a certain chunk of the world. We work out the provider for the tile the chunk is in, and then all the providers for all the tiles that are within the maximum radius of that tile. We now have every provider that could influence this chunk. We call the first function on each of them, if they haven't been called already, and register what chunks each of them has claimed into a global map.
At this point, we've consulted everything that could have an influence on this chunk. We then ask that registry if someone has claimed this chunk. If so, we call back into that provider (method #2) with the chunk and the world instance and get it to draw the bits for this part of its structure.
Does that give you enough of an idea for a general approach to your problem?