Показать сообщение отдельно
Старый 20.07.2014, 18:09   #25
WISHMASTER35
Бывалый
 
Аватар для WISHMASTER35
 
Регистрация: 21.12.2008
Адрес: UA
Сообщений: 878
Написано 105 полезных сообщений
(для 357 пользователей)
Ответ: Еще один Minecraft на юнити

Производительность 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 сек.
(Offline)
 
Ответить с цитированием
Эти 6 пользователя(ей) сказали Спасибо WISHMASTER35 за это полезное сообщение:
Igor (24.07.2014), impersonalis (20.07.2014), Mr_F_ (20.07.2014), pax (21.07.2014), Randomize (21.07.2014), St_AnGer (20.07.2014)