Производительность Mono - дело весьма странное.
Порой, чтобы функция работала в 2 раза быстрее, ее нужно разбить на несколько функций.
Наверно самым тормозным местом является функция получения соседних блоков. Переводить мировые координаты в координаты grid и local, а потом еще в индексы для массива - дело медленное. Поэтому написал такую весьма запутанную функцию.
public DataBlock GetAdjacentBlock(int localIndex, CubeSide side) {
const int LOCAL_MASK_X = Chunk.X_MASK; // 001
const int LOCAL_MASK_Y = Chunk.Y_MASK << Chunk.X_BITS; // 010
const int LOCAL_MASK_Z = Chunk.Z_MASK << Chunk.Y_BITS << Chunk.X_BITS; // 100
// zzzzzyyyyyxxxxx
const int CHUNK_DELTA_X = 1;
const int CHUNK_DELTA_Y = ChunkGrid.X_SIZE;
const int CHUNK_DELTA_Z = (ChunkGrid.X_SIZE * ChunkGrid.Y_SIZE);
const int LOCAL_DELTA_X = Chunk.X_SIZE - 1;
const int LOCAL_DELTA_Y = Chunk.X_SIZE * (Chunk.Y_SIZE - 1);
const int LOCAL_DELTA_Z = Chunk.X_SIZE * Chunk.Y_SIZE * (Chunk.Z_SIZE - 1);
switch(side) {
case CubeSide.Front: // z+
if((localIndex | LOCAL_MASK_Z) == localIndex) { // index == max
if(position.z == ChunkGrid.Z_MAX) return default( DataBlock );
int chunkIndex = this.chunkIndex + CHUNK_DELTA_Z;
localIndex -= LOCAL_DELTA_Z;
return Map.instance.GetBlock(chunkIndex, localIndex);
} else {
return blocks[ localIndex + (Chunk.X_SIZE * Chunk.Y_SIZE) ];
}
case CubeSide.Back: // z-
if((localIndex & ~LOCAL_MASK_Z) == localIndex) { // index == min
if(position.z == 0) return default( DataBlock );
int chunkIndex = this.chunkIndex - CHUNK_DELTA_Z;
localIndex += LOCAL_DELTA_Z;
return Map.instance.GetBlock( chunkIndex, localIndex );
} else {
return blocks[localIndex - (Chunk.X_SIZE * Chunk.Y_SIZE)];
}
case CubeSide.Right: // x+
if((localIndex | LOCAL_MASK_X) == localIndex) { // index == max
if(position.x == ChunkGrid.X_MAX) return default( DataBlock );
int chunkIndex = this.chunkIndex + CHUNK_DELTA_X;
localIndex -= LOCAL_DELTA_X;
return Map.instance.GetBlock( chunkIndex, localIndex );
} else {
return blocks[localIndex + 1];
}
case CubeSide.Left: // x-
if((localIndex & ~LOCAL_MASK_X) == localIndex) { // index == min
if(position.x == 0) return default( DataBlock );
int chunkIndex = this.chunkIndex - CHUNK_DELTA_X;
localIndex += LOCAL_DELTA_X;
return Map.instance.GetBlock( chunkIndex, localIndex );
} else {
return blocks[localIndex - 1];
}
case CubeSide.Top: // y+
if((localIndex | LOCAL_MASK_Y) == localIndex) { // index == max
if(position.y == ChunkGrid.Y_MAX) return default( DataBlock );
int chunkIndex = this.chunkIndex + CHUNK_DELTA_Y;
localIndex -= LOCAL_DELTA_Y;
return Map.instance.GetBlock( chunkIndex, localIndex );
} else {
return blocks[localIndex + Chunk.X_SIZE];
}
case CubeSide.Bottom: // y-
if((localIndex & ~LOCAL_MASK_Y) == localIndex) { // index == min
if(position.y == 0) return default( DataBlock );
int chunkIndex = this.chunkIndex - CHUNK_DELTA_Y;
localIndex += LOCAL_DELTA_Y;
return Map.instance.GetBlock( chunkIndex, localIndex );
} else {
return blocks[localIndex - Chunk.X_SIZE];
}
}
return default(DataBlock);
}
Теперь время снизилось с ~20 сек. до ~7 сек.
Если разделить это все на 7 функций:
public DataBlock GetAdjacentBlock(int localIndex, CubeSide side) {
switch(side) {
case CubeSide.Front: return GetFrontBlock( localIndex );
case CubeSide.Back: return GetBackBlock( localIndex );
case CubeSide.Right: return GetRightBlock( localIndex );
case CubeSide.Left: return GetLeftBlock( localIndex );
case CubeSide.Top: return GetTopBlock( localIndex );
case CubeSide.Bottom: return GetBottomBlock( localIndex );
}
return default(DataBlock);
}
Теперь скорость ~4.9 сек. И это еще тратиться некоторое время на еще один вызов функции.
А если напрямую вызывать эти функции:
DataBlock b1 = chunk.GetFrontBlock( i );
DataBlock b2 = chunk.GetBackBlock( i );
DataBlock b3 = chunk.GetRightBlock( i );
DataBlock b4 = chunk.GetLeftBlock( i );
DataBlock b5 = chunk.GetTopBlock( i );
DataBlock b6 = chunk.GetBottomBlock( i );
Тогда вообще ~2.9 сек.