Along with their troubled System Shock 2 remake, Night Dive Studios have been working on remastering the first two Turok games since at least early 2016. Thankfully, that project isn’t troubled, and will launch early next month.

Night dive has announced that both games will release on Microsoft’s console on March 2. The games will be $20 apiece. These remasters seem to be light on new features, sticking instead of revitalizing the core experience of the titles under a new engine. You can watch a trailer below to see how the remaster of the first Turok looks in action.

Our Take Can’t say I’ve ever been a Turok fan, but even if I was, $20 for each game seems a bit pricey. I can certainly admire the work put into these remasters, but the price seems just a bit too high.

MENLO PARK, Calif.—An iconic, family-run burger-and-pizza pub that has been operating in the heart of Silicon Valley for 60 years announced this week that it would close for good on March 7 due to an unaffordable rent.

In addition to being a local favorite, The Oasis Beer Garden—a short drive away from nearby Stanford University—also has a special place in the heart of many of the region’s early tech pioneers.

Members of the legendary Homebrew Computer Club—a 1970s-era monthly club that met in the early days of personal computing—would often relocate to “The O” as the night wore on.

Twitch’s new reality show featuring up-and-coming streamers will premiere on March 8, the company announced this morning, along with the list of the fourteen personalities selected to participate. The video stars will be competing over an 11-week period for the chance to win $60,000, paid out as $5,000-per-month installments, meant to help fund their streaming careers.
“Stream… Read More

Bitcoin is volatile. Other cryptocurrencies, like Ethereum, rocket to the moon before chaotically tumbling back to Earth. Unstable prices, the lure of a waiting fortune, and good old FUD contribute to the rise in cryptocurrency mining. Application-specific integrated circuit (ASIC) miners led the first crypto-mining boom. Ethereum and Ethereum-based altcoins lead the second. And it is GPUs, not ASIC mining hardware, that is powering the second boom. The regular graphics cards that we use to bring Skyrim and Rocket League into our lives are also powering the booming cryptocurrency market. As such, GPU prices (much like cryptocurrencies) are stratospheric right…

Depth sorting can be explained in simple terms as a way of figuring out
which element is nearer to the camera and which is farther away, thereby
determining the order in which they need to be arranged in order to
convey the right depth in the scene.

In this tutorial, we will dig deeper into depth sorting for isometric levels as we try to add moving platforms. This is not a beginner tutorial on isometric theory and is not about the code. The focus is to understand the logic and theory rather than to dissect the code. The tool of choice for the tutorial is Unity, and hence depth sorting essentially is changing the sortingOrder of the sprites involved. For other frameworks, it may be a changing of the z order or the sequence of drawing order.

In order to get started on isometric theory, please refer to this tutorial series. The code and scene structure follow my previous isometric tutorial. Please refer to these if you find the tutorial hard to follow as I will be focusing only on logic in this tutorial.

1. Levels Without Movement

If your isometric level does not have any moving elements or just has a few characters walking over the level, the depth sorting is straightforward. In such cases, the characters occupying the isometric tiles would be smaller than the tiles themselves and can easily just use the same drawing order/depth as the tile they occupy.

Let’s refer to such motionless levels as static levels. There are a few ways in which such levels can be drawn so that the right depth is conveyed. Typically, the level data will be a two-dimensional array where the rows and columns will correspond to the rows and columns of the level.

Consider the following isometric level with just two rows and seven columns.

The numbers on the tiles indicate their sortingOrder
or depth or z order, i.e. the order in which they need to be drawn. In
this method, we are drawing all the columns in the first row, starting
with the first column with a sortingOrder of 1.

Once all columns are drawn in the first row, the nearest column to the camera has a sortingOrder of 7, and we proceed to the next row. So any element in the second row will have a higher sortingOrder than any element of the first row.

This is exactly how the tiles need to be arranged to convey the correct depth as a sprite with a higher sortingOrder will get overlaid over any other sprites with lower sortingOrder.

As for the code, this is just a matter of looping through the rows and columns of the level array and assigning sortingOrder sequentially in an increasing order. It would not break, even if we swap rows and columns, as can be seen in the image below.

Here we draw a complete column first before moving to the next row. The depth perception stays intact. So the logic for a static level is to draw either a complete row or complete column and then proceed to the next while assigning sortingOrder sequentially in an increasing order.

Adding Height

If we consider the level as a building, we are currently drawing the ground floor. If we need to add a new floor to our building, all we need to do is to wait till we draw the whole ground floor first and follow the same method for the next floor.

For proper depth, we waited till the full row was complete before we moved to the next row, and similarly we wait till all the rows are complete before we move to the next floor. So for a level with only a single row and two floors, it would look like the image below.

Essentially, any tile on the higher floor will have a higher sortingOrder than any tile on the lower floor. As for the code for adding higher floors, we just need to offset the y value of the screen coordinates for the tile, depending on which floor it occupies.

The floorHeight value indicates the perceived height of the isometric block tile image, whereas floorLevel indicates which floor the tile occupies.

2. Moving Tiles on the X Axis

Depth sorting on a static isometric level was not complicated, right? Moving on, let us decide to follow the row first method, where we assign sortingOrder to the first row completely and then proceed to the next. Let’s consider our first moving tile or platform which moves on a single axis, the x axis.

When I say that the motion is on the x axis, you need to realize that we are
talking about the cartesian coordinate system and not the isometric
coordinate system. Let’s consider a level with only a ground floor of three rows and seven columns. Let’s also consider that the second row only has a single tile, which is our moving tile. The level will look like the image below.

The dark tile is our moving tile, and the sortingOrder it would get assigned will be 8 as the first row has 7 tiles. If the tile moves on the cartesian x axis then it will move along the trench between the two rows. At all of the positions it may occupy along that path, the tiles in row 1 will have a lesser sortingOrder.

Similarly, all the tiles in row 2 will have a higher sortingOrder, irrespective of the position of the dark tile along said path. So as we follow a row first method of assigning sortingOrder, we do not need to do anything for motion on the x axis. Now, that was easy.

3. Moving Tiles on the Y Axis

Problems start to arise when we start considering the y axis. Let’s consider a level in which our dark tile is moving along a rectangular trench, as shown below. You can see the same in the MovingSortingProblem Unity scene in the source.

Using our row first approach, we can provide a sortingOrder for our moving tile based on the row it currently occupies. When the tile is between two rows, it would get assigned a sortingOrder based on the row it is moving from. In that case, it cannot follow the sequential sortingOrder in the row into which it is moving. This essentially breaks our depth sorting approach.

Sorting in Blocks

In order to solve this, we need to divide our level into different blocks, among which one is the problem block, which breaks under our row first approach, and the rest are blocks which can follow the row first approach without breaking. Consider the image below for a better understanding.

The 2×2 tile block represented by the blue area is our problem block. All the other blocks can still follow the row first approach. Please do not be confused by the image as it shows a level which is already properly sorted using our block approach. The blue block consists of the two column tiles in the rows between which our dark tile is currently moving and the tiles immediately to the left of them.

In order to solve the depth issue for the problem block, we can use the column first approach for this block alone. So for the green, pink, and yellow blocks, we use row first, and for the blue block, we use the column first approach.

Notice that we still need to sequentially assign the sortingOrder. First the green block, then the pink block to the left, then the blue block, now comes the pink block to the right, and finally the yellow block. We break the order only to switch to the column first approach while at the blue block.

Alternatively, we can also consider the 2×2 block to the right of the moving tile column. (The interesting thing is, you do not even need to switch approaches as breaking into blocks itself has already solved our problem in this case.) The solution can be seen in action in the BlockSort scene.

This translates to code as below.

private void DepthSort(){
Vector2 movingTilePos=GetLevelIndicesFromScreenPoint(movingGO.transform.position);
int blockColStart=(int)movingTilePos.y;
int blockRowStart=(int)movingTilePos.x;
int depth=1;
//sort rows before block
for (int i = 0; i < blockRowStart; i++) {
for (int j = 0; j < cols; j++) {
depth=AssignDepth(i,j,depth);
}
}
//sort columns in same row before the block
for (int i = blockRowStart; i < blockRowStart+2; i++) {
for (int j = 0; j < blockColStart; j++) {
depth=AssignDepth(i,j,depth);
}
}
//sort block
for (int i = blockRowStart; i < blockRowStart+2; i++) {
for (int j = blockColStart; j < blockColStart+2; j++) {
if(movingTilePos.x==i&&movingTilePos.y==j){
SpriteRenderer sr=movingGO.GetComponent<SpriteRenderer>();
sr.sortingOrder=depth;//assign new depth
depth++;//increment depth
}else{
depth=AssignDepth(i,j,depth);
}
}
}
//sort columns in same row after the block
for (int i = blockRowStart; i < blockRowStart+2; i++) {
for (int j = blockColStart+2; j < cols; j++) {
depth=AssignDepth(i,j,depth);
}
}
//sort rows after block
for (int i = blockRowStart+2; i < rows; i++) {
for (int j = 0; j < cols; j++) {
depth=AssignDepth(i,j,depth);
}
}
}

4. Moving Tiles on the Z Axis

A motion in the z axis is a fake motion on an isometric level. It essentially is just motion on the screen y axis. For a single-floor isometric level, there is nothing more to do in order to add motion on the z axis if you have already done the block sorting method described above. You can see this in action in the SingleLayerWave Unity scene, where I have added an additional wave motion on the z axis along with the lateral trench movement.

Z Movement on Levels With Multiple Floors

Adding an additional floor to your level is just a matter of offsetting the
screen y coordinate, as explained before. If the tile does not move on the z
axis then there is no need to do anything special for depth sorting. We
can block sort the ground floor with motion and then apply row first
sorting to each successive floor. You can see this in action in the BlockSortWithHeight Unity scene.

A very similar depth problem arises when the tile starts moving between floors. It can only satisfy the sequential order of one floor using our approach and would break the depth sorting of the other floor. We need to extend or modify our block sorting to three dimensions to deal with this depth problem with floors.

The problem essentially will be just the two floors between which the tile is currently moving. For all other floors, we can stick to our current sorting approach. Special needs apply to only these two floors, among which we can first determine the lower floor as below where tileZOffset is the amount of motion on the z axis for our moving tile.

This means that lower and lower+1 are the floors which need a special approach. The trick is to assign sortingOrder for both these floors together, as shown in the code below. This fixes the sequence so that the depth issues are sorted out.

if(floor==lower){
// we need to sort lower floor and the floor just above it together in one go
depth=(floor*(rows*cols))+1;
int nextFloor=floor+1;
if(nextFloor>=totalFloors)nextFloor=floor;
//sort rows before block
for (int i = 0; i < blockRowStart; i++) {
for (int j = 0; j < cols; j++) {
depth=AssignDepth(i,j,depth,floor);
depth=AssignDepth(i,j,depth,nextFloor);
}
}
//sort columns in same row before the block
for (int i = blockRowStart; i < blockRowStart+2; i++) {
for (int j = 0; j < blockColStart; j++) {
depth=AssignDepth(i,j,depth,floor);
depth=AssignDepth(i,j,depth,nextFloor);
}
}
//sort block
for (int i = blockRowStart; i < blockRowStart+2; i++) {
for (int j = blockColStart; j < blockColStart+2; j++) {
if(movingTilePos.x==i&&movingTilePos.y==j){
SpriteRenderer sr=movingGO.GetComponent<SpriteRenderer>();
sr.sortingOrder=depth;//assign new depth
depth++;//increment depth
}else{
depth=AssignDepth(i,j,depth,floor);
depth=AssignDepth(i,j,depth,nextFloor);
}
}
}
//sort columns in same row after the block
for (int i = blockRowStart; i < blockRowStart+2; i++) {
for (int j = blockColStart+2; j < cols; j++) {
depth=AssignDepth(i,j,depth,floor);
depth=AssignDepth(i,j,depth,nextFloor);
}
}
//sort rows after block
for (int i = blockRowStart+2; i < rows; i++) {
for (int j = 0; j < cols; j++) {
depth=AssignDepth(i,j,depth,floor);
depth=AssignDepth(i,j,depth,nextFloor);
}
}
}

Essentially, we are considering two floors as a single floor and doing a block sort on that single floor. Check out the code and action in the scene BlockSortWithHeightMovement. With this approach, our tile is now free to move on any of the two axes without breaking the depth of the scene, as shown below.

Conclusion

The idea of this tutorial was to clarify the logic of the depth sorting approaches, and I hope you have fairly understood this. It is evident that we are considering comparatively simple levels with only one moving tile.

There are no slopes either as including slopes would have made this a much longer tutorial. But once you have understood the sorting logic, then you can try to extend the two-dimensional slope logic to the isometric view.

Unity has an active economy. There are many other products that help you build out your project. The nature of the platform also makes it a great option from which you can better your skills. Whatever the case, you can see what we have available in the Envato Market.