Lançamento de outubro de 2026
No mês passado, escrevi que a série 2.x receberia apenas mudanças compatíveis e que a próxima quebra de compatibilidade ficaria para a 3.0. Ela chegou em outubro e vem acompanhada de um guia de migração.
Outubro foi o mês em que o Turian deixou de ser um editor com renderizador e se tornou uma engine na qual dá para criar um jogo. Agora os objetos caem e colidem. Uma câmera desenha apenas o que vê, e dez mil cópias de uma caixa custam uma única passada no renderizador. Designers podem conectar a lógica do jogo usando assets. Um script pode ser assícrono sem usar corrotinas, e um jogo pode salvar seu progresso. O mesmo projeto pode exportar um cliente com janela ou um servidor sem janela alguma. E o Studio, o editor onde tudo isso é construído, finalmente tem uma visualização de cena que se comporta como as que você já conhece.

- Por que uma versão 3.0
- Os objetos caem: física 3D
- Desenhar menos, desenhar mais rápido
- Linhas, rastros e palavras no mundo
- Designers conectam o jogo
- Tempo, espera e salvamento
- A visualização de cena amadurece
- Um novo visual
- Turian sem janela
- Guinevere da versão 5.7 à 6.5
- Com a sua ajuda
Por que uma versão 3.0
Turian 3.0.0, issues #35, #47, #62, #213
Duas frentes exigiam mudanças incompatíveis. O renderizador precisava sair do núcleo da engine para que uma compilação para servidor deixasse de carregar o Vulkan. E os temas precisavam adotar um formato real de folhas de estilo, porque as antigas tabelas de cores não conseguiam expressar o que o Material 3 exigia. Ambos já estavam em andamento quando a versão 2.0 saiu. Adiá-los só aumentaria a quantidade de projetos 2.x que precisariam migrar depois.
Como na 2.0, as quebras foram reunidas em um único lançamento, com um único guia de migração:
| Mudança | Quem é afetado | Como atualizar |
|---|---|---|
| O renderizador Vulkan virou um brick | código que usava tipos do renderizador diretamente; projetos existentes recebem o brick automaticamente | Renderizador |
| Configurações e perfis de compilação são registrados em um asset de projeto | todos os projetos, convertidos automaticamente ao abrir | Asset de projeto |
| glTF virou o formato interno de malhas, e a importação de OBJ passou a ser um brick opcional | projetos com modelos .obj, jogos exportados e ferramentas de malhas |
Modelos |
Temas de cores viraram folhas de estilo .pss |
temas personalizados e plugins que leem cores dos temas | Temas |
| As configurações do Gaya obtêm sua configuração por atributos de classe | plugins com páginas de configurações ou widgets na barra de abas | Gaya |
| O Guinevere 6 mudou o desenho e a estilização | código que desenha diretamente com o Guinevere | Guinevere |
Cenas, prefabs e DataAssets mantêm seus IDs, então seu conteúdo não precisa de conversão. Todos os lançamentos posteriores à 3.0.0 foram compatíveis.
Os objetos caem: física 3D
Turian 3.5.0 e 3.6.0, issues #64, #48, #111
A física era a maior lacuna entre o Turian e as engines com as quais ele é comparado. Essa lacuna foi preenchida neste mês e, como tudo que é opcional no Turian, chegou na forma de bricks.
São dois. O org.mass4.turian.physics contém os componentes, as configurações e um contrato de backend, mas não simula nada sozinho. O org.mass4.turian.physics.bepu conecta o BepuPhysics v2 a esse contrato. O Bepu é uma biblioteca de física úper rápida e multithread escrita inteiramente em C#, então dispensa binários nativos e funciona onde o .NET funcionar. Instale ambos e os objetos começam a cair. A camada de interface não faz referência ao Bepu, permitindo substituí-lo por outro backend no futuro sem alterar suas cenas.
Se você conhece a física do Unity, já conhece esta. Os nomes e comportamentos seguem os dele de propósito:
- Corpos rígidos: massa, amortecimento, gravidade, modo cinemático, interpolação, detecção contínua de colisões, eixos bloqueados e centro de massa. As forças usam o
ForceModedo Unity. - Colisores: caixa, esfera, cápsula, cilindro, malha e campo de alturas. Vários colisores em um mesmo corpo formam um colisor composto; um colisor sem corpo é estático.
- Juntas: fixa, dobradiça, deslizante, esférica, de distância e de mola. Dobradiças e juntas deslizantes têm motores, limites e molas.
- Um controlador de personagem com
MoveeSimpleMoveque sobe degraus e rampas e acompanha plataformas móveis. - Colisores de rodas para veículos baseados em raycasts, com suspensão, curvas de atrito dos pneus, torque de motor e freio e direção.
- Materiais físicos como DataAssets, com atrito, elasticidade e os modos de combinação do Unity.
- Consultas: raycasts, varreduras de formas, sobreposições e testes de penetração, filtrados pelas camadas de física que chegaram com as tags e camadas no início do mês.
- Callbacks: Enter, Stay e Exit para colisões e gatilhos, em qualquer componente que implemente a interface de tratamento.
- Ragdolls:
RagdollBuilder.FromSkeletonajusta cápsulas e juntas com limites aos ossos de um esqueleto. O rig alterna entre acompanhar a animação e cair sob a ação da física, e pode retornar à pose de vinculação.

Em um projeto de benchmark, uma chuva despeja 200 caixas por segundo até chegar a 10.000. Na minha estação de trabalho, o jogo exportado mantém cerca de 80 quadros por segundo com todas ainda ativas. Quando a pilha se acomoda, todas entram em repouso e um passo de física custa uma fração de milissegundo. São números de uma única máquina, não uma promessa. Ainda assim, melhoraram ao longo do mês, porque a análise de desempenho também encontrou e eliminou alocações em outras partes da engine.

O que ainda falta: um editor dedicado à matriz de colisão entre camadas (o Inspector a mostra como 32 máscaras brutas) e determinismo entre máquinas. O Bepu é determinístico apenas na mesma máquina.
Desenhar menos, desenhar mais rápido
Turian 2.1.0, 3.0.0 e 3.2.0, issues #8, #59, #104
O desenho mais rápido é aquele que você dispensa.
Descarte por frustum
Uma câmera enxerga apenas o que está dentro do seu frustum, o volume entre os planos próximo e distante. Até este mês, o renderizador enviava todas as malhas à GPU e deixava que ela descartasse o que caía fora da tela. Agora cada submalha mantém seus limites em espaço global em cache, e tudo que fica fora da câmera ativa é descartado antes mesmo de registrar uma chamada de desenho ou procurar seu material. Isso funciona com nós rotacionados e escalados, modelos procedurais e câmeras em perspectiva ou ortográficas.
Em uma cena de benchmark, uma rua grande com cerca de 1.600 submalhas, vista por cinco câmeras:
| Câmera | Descarte desativado | Descarte ativado | Enviadas | Descartadas | Pixels alterados |
|---|---|---|---|---|---|
| Principal | 2.43 ms | 2.12 ms | 1,322 | 269 | 0 |
| Visão geral | 2.47 ms | 2.43 ms | 1,591 | 0 | 0 |
| Sul | 2.55 ms | 2.48 ms | 1,521 | 70 | 0 |
| Oeste | 2.25 ms | 1.76 ms | 634 | 957 | 0 |
| Leste | 1.93 ms | 1.05 ms | 44 | 1,547 | 0 |
A câmera de visão geral enxerga a rua inteira, então não há o que descartar. A câmera leste vê apenas um canto, descarta quase tudo e reduz o tempo de quadro quase pela metade. Em todos os casos, a imagem é idêntica, pixel por pixel.
Instanciamento na GPU
Chamadas de desenho têm um custo próprio: cada uma consome tempo de CPU para ser registrada, por menor que seja a malha. Agora o renderizador reúne cada sequência de malhas e materiais idênticos em um único desenho instanciado. Dez mil objetos idênticos que antes custavam 8.791 chamadas de desenho agora custam uma, com os mesmos pixels. Cada cópia ainda pode ter sua própria tonalidade e quatro valores personalizados sem dividir o lote.
Para sistemas com muitas cópias de um modelo, como vegetação, multidões ou detritos, o novo componente Instanced Model desenha tudo a partir de um único buffer na GPU, envia apenas as instâncias alteradas e faz o descarte do conjunto inteiro de uma vez: 10.000 cubos coloridos consomem cerca de 0,6 ms de CPU. Clicar em qualquer instância na visualização de cena continua selecionando seu nó.

Enxergando o quadro
Todos esses números ficam visíveis sem um profiler. O HUD de estatísticas de quadro sobrepõe às visualizações Scene e Game o tempo de quadro, as chamadas de desenho, as instâncias e as contagens de envio e descarte. Capturas sem interface informam os mesmos contadores, permitindo detectar regressões em tarefas de CI. O próprio Studio agora renderiza sob demanda: quando nada muda, ele para de redesenhar e deixa a GPU para o seu jogo.
Linhas, rastros e palavras no mundo
Turian 3.8.0, issue #110
Três pequenos componentes:
LineRendererdesenha um caminho por uma lista de pontos, plano ou sempre voltado para a câmera, com curvas de largura e cor ao longo do comprimento e uma textura opcional esticada ou repetida. Principalmente para lasers e cordas.TrailRendererregistra por onde seu nó passou e desenha uma faixa que desaparece com o tempo. Golpes de espada, marcas de pneus, a cauda de um cometa.WorldTextComponentposiciona texto no mundo 3D com qualquer fonte que o Guinevere consiga carregar. O desenho usa um campo de distância com sinal, mantendo a nitidez em qualquer distância e ângulo. Números de dano e placas de sinalização.
Os três respeitam as camadas de renderização, são ordenados junto à geometria transparente e funcionam tanto na visualização de cena quanto no jogo. Também ajudam na depuração: as cenas de teste de física os usam para desenhar linhas de consulta, rastros e números flutuantes de colisões.

Designers conectam o jogo
Turian 2.2.0 e 3.7.0, issues #91, #55
Em setembro, prometi que os DataAssets seriam a base do trabalho dos designers e citei a palestra de Ryan Hipple de 2017 sobre arquitetura com ScriptableObjects. Outubro trouxe o padrão em si: os assets daquela palestra e as ferramentas do Studio para conectá-los e depurá-los.
Eventos, variáveis e listeners como assets
O novo brick org.mass4.turian.ddd, de DataAsset-Driven Design (design orientado a DataAssets), traz ao Turian as famílias de assets daquela palestra:
- Eventos, com ou sem dados associados: “jogador morreu”, “moeda coletada”, “porta aberta”.
- Variáveis e constantes: a vida do jogador é um asset
FloatVariablelido pela barra de vida, pelo áudio e pelo sistema de salvamento, e todos são notificados quando ela muda. - Conjuntos de execução: “todos os inimigos vivos agora”, mantidos pelos próprios inimigos conforme surgem e morrem.
- Listeners e respostas, para reagir a eventos sem scripts.
- Enums como assets com transições de estado, para estados como menu, jogando e pausado.
- Um leitor de entrada que transforma ações de entrada em eventos e variáveis.
Um campo de componente do tipo DataAssetReference<T> aceita um valor simples ou um asset de variável. Assim, o designer decide se o valor é local ou compartilhado sem pedir uma alteração de código. Os botões do brick de UI podem disparar eventos e acompanhar diretamente variáveis Enabled e Visible.
Disparar um evento não gera alocações e custa cerca de 4 ns com um listener e 12 ns com oito. É barato o suficiente para a lógica do jogo, embora eu ainda mantenha os callbacks da engine a cada tick e contato como chamadas diretas.
O brick complementar org.mass4.turian.ddd.studio adiciona as ferramentas. Create → DDD no painel Assets cria cada família de assets, e View → DataAsset Overview mostra quem dispara, escuta e referencia cada asset, além de encontrar os que não são referenciados. Validate wires identifica destinos ausentes e tipos incompatíveis de dados. No modo Play, você pode disparar eventos pelo editor, observar o valor de uma variável em tempo real e alterá-lo. Para seus próprios tipos de dados, o DDD Type Generator escreve as classes de eventos, variáveis e conjuntos.
Ainda faltam: listas e dicionários como assets, cópias privadas de variáveis por instância de prefab e salvamento de variáveis, que usará o brick de salvamento em vez de um formato próprio.
Tags e camadas
Agora os nós podem ter várias tags de texto, encontradas por consultas indexadas de cena como FindAllWithTag, além de camadas separadas de física e renderização, com 32 posições cada. Câmeras e luzes podem filtrar por camada de renderização, e a visualização de cena pode ocultar ou bloquear camadas. As tabelas ficam em um DataAsset de configurações de Tags and Layers com IDs estáveis: renomear ou reordenar uma entrada não quebra cenas ou prefabs que a utilizam. O conteúdo existente é carregado como Untagged nas camadas Default sem reescrever arquivos. O design para o qual essas tabelas estão evoluindo merece um post próprio: Tags e camadas como assets.
Tempo, espera e salvamento
Turian 2.1.0, 3.2.0 e 3.3.0, issues #155, #88, #89
Esperando sem corrotinas
Scripts no Unity esperam com corrotinas, e a maioria dos projetos grandes acaba substituindo-as pelo UniTask. O Turian vai direto ao async e await do próprio C#. Todo componente tem uma propriedade Async com esperas vinculadas ao seu tempo de vida:
public class Door : Component
{
public bool IsBlocked { get; set; }
public async ValueTask OpenAsync()
{
Node.Position += Vector3.UnitY;
await Async.Seconds(2); // tempo de jogo com escala
await Async.Until(() => !IsBlocked);
Node.Position -= Vector3.UnitY;
}
}
Há esperas pelo próximo quadro, próximo tick fixo, segundos com e sem escala, tempo real e tempo de ticks fixos, além de condições que se tornam verdadeiras ou falsas. Toda continuação volta ao loop do jogo, nunca a uma thread de trabalho. Quando o componente é destruído, suas esperas pendentes são canceladas em vez de serem executadas em um objeto que já não existe. A pausa do Studio congela as esperas de tempo de jogo e mantém as de tempo real contando. Uma espera pendente não aloca memória, e o compilador sinaliza erros clássicos no código do jogo, como async void, Task.Delay e armazenar um ValueTask.
Um relógio confiável
Um asset TimeSettings agora define a taxa fixa da simulação e quantos ticks um quadro lento pode recuperar. Por trás dele, um relógio compartilhado de simulação conta os ticks concluídos, pausa e avança passo a passo. Sobre esse relógio, SimulationSession oferece ao jogo um mundo autoritativo que aceita comandos, elimina duplicatas, numera seus ticks e mantém fluxos aleatórios nomeados e reproduzíveis. O modo Play, o player sem interface e o jogo exportado compartilham a mesma fronteira de tick. Um mundo de teste produz o mesmo hash de estado a cada tick com a tela a 30, 60 ou 144 Hz, inclusive após salvar e retomar. A rede em si ainda não chegou, mas essa será sua base.
Salvando o jogo
O RuntimeSave, de setembro, cria checkpoints da simulação. O novo brick org.mass4.turian.save permite ao jogo guardar esses checkpoints e seus próprios dados de salvamento em um lugar seguro:
- Esquemas versionados. Cada salvamento registra a versão do esquema do jogo. Ao carregar, uma cadeia de migrações atualiza salvamentos antigos uma versão por vez, sem reescrever o arquivo armazenado.
- Tudo substituível. JSON por padrão, com suporte a qualquer serializador (MemoryPack, MessagePack, protobuf) ou formato de contêiner. Inclui criptografia AES-GCM opcional.
- Sem perdas. A escrita vai primeiro para um arquivo temporário e só substitui o slot quando termina. A geração anterior é mantida como backup, e arquivos corrompidos são denunciados em vez de carregados silenciosamente.
- Conflitos detectados. Cada escrita informa a revisão que espera substituir, impedindo que duas máquinas ou processos sobrescrevam silenciosamente os dados um do outro. O mesmo contrato vale para armazenamento em nuvem, com um exemplo que simula um conflito de salvamento.
Não depende do renderizador nem de serializadores de terceiros, então funciona em clientes, servidores dedicados e testes.

A visualização de cena amadurece
Turian 2.1.0 a 3.0.0, issues #82, #68
A maior parte do tempo no editor é passada na visualização de cena, então foi ali que se concentrou o trabalho no Studio em outubro.
Gizmos. Os manipuladores de transformação foram refeitos: setas mais grossas, caixas de escala sólidas, manipuladores preenchidos de dois eixos e arcos de rotação que se voltam para a câmera, destacam-se ao passar o cursor e mostram o ângulo percorrido durante o arraste. A rotação funciona nos eixos globais ou locais, com encaixe por ângulo. Uma ferramenta combinada mostra movimento, rotação e escala ao mesmo tempo. Os manipuladores permanecem visíveis à frente da geometria, permitindo mover até objetos escondidos dentro de paredes.
Orientação. Um controle compacto ocupa o canto: um pequeno cubo com eixos identificados. Clique em um eixo para olhar ao longo dele e no centro para alternar entre perspectiva e ortográfica sem perder o enquadramento. A grade de referência agora é recortada corretamente junto à câmera e usa o plano XZ por padrão, com eixos de origem coloridos. Uma página de configurações controla seu espaçamento, destaque e opacidade.

Navegação. O controle de visão com o botão direito mantém o horizonte nivelado e não permite virar a câmera de cabeça para baixo. As setas movem a câmera por atalhos contínuos e editáveis, e Shift aumenta a velocidade. O painel Scene reúne ferramentas, espaço de coordenadas e encaixe em uma barra compacta de ícones. A configuração Cap FPS evita que o Studio ocioso aqueça seu notebook.
Edição de múltiplos objetos. A hierarquia e o painel Assets aceitam Ctrl+clique, intervalos com Shift+clique e Selecionar Tudo; a visualização de cena aceita seleção retangular. O Inspector mostra os componentes comuns à seleção, com valores diferentes indicados por “—”. Edite um campo compartilhado e todos os objetos selecionados mudam. Edite um eixo da transformação e os demais preservam seus valores individuais. Exclusão, duplicação, troca de pai e movimento em lote podem ser desfeitos em um único passo cada.

E o restante. No histórico de commits, isso foi resumido como “1001 correções que estavam me deixando louco”, o que descreve bem a situação. As primeiras que você vai notar:
- Cenas temporárias. File → New Scene (Ctrl+N) abre uma cena para experimentar, sem criar um asset até que você a salve.
- Um painel Assets reformulado.
- Um cartão de carregamento mostra o que o Studio está importando e compilando durante a abertura de um projeto.
- Reabertura mais rápida. O projeto reutiliza os arquivos importados quando nada mudou, e Build & Run copia apenas os assets alterados.
Um novo visual
Turian 3.0.0, issues #212, #213, #214, #215, #217
O Studio agora usa por padrão o Material 3, o sistema de design atual do Google, desenhado pelo Guinevere.
Por baixo, a aparência se divide em quatro escolhas independentes: o visual (a forma de cada controle), o tema de cores, o conjunto de ícones e as fontes. Os temas são folhas de estilo .pss, a interpretação de CSS do Guinevere, e recarregam em tempo real enquanto você os edita. Os conjuntos de ícones têm versões Mono e Color.
Visuais e temas são bricks, então qualquer pessoa pode criá-los e compartilhá-los. O turian-cli empacota temas como bricks pela linha de comando. O painel Bricks foi movido para o Gaya, com escopos separados para os bricks do próprio Studio e os de cada projeto. Os dois primeiros visuais adicionais trazem nostalgia: Windows XP e Windows 9x, instalados como qualquer outro brick.
A UI do jogo também ganha: com Vulkan, ela agora é renderizada na GPU.
Turian sem janela
Turian 3.0.0 a 3.8.0, issues #35, #62, #292, #313, #344
Nem toda compilação de um jogo tem uma tela. Um servidor dedicado ou uma simulação sem interface em CI não precisa de GPU nem deveria precisar incluir suporte a ela no pacote.
- Perfis de compilação. Um projeto agora contém vários perfis, cada um com plataforma, função de cliente ou servidor, configuração e seus próprios símbolos de compilação e ajustes, editados na janela Build Profiles. O arquivo
Assets/Project.dataassetos registra junto das configurações do projeto e da versão da engine que o salvou pela última vez. - Servidores sem interface. Como o renderizador é um brick, o perfil de servidor simplesmente o omite. O player sem interface executa as mesmas cenas e os mesmos ticks de simulação, e encerra corretamente com Ctrl+C.
- Servidores NativeAOT. Um perfil de servidor para desktop pode compilar antecipadamente para um único executável nativo, sem instalar o runtime .NET nem aguardar o aquecimento do JIT. O editor gera o código de inicialização que antes dependia de reflexão, e qualquer parte ausente gera um erro claro na exportação, em vez de durante a execução. Nossos servidores de teste exportam, executam e encerram corretamente, sem avisos de trimming.
- Bricks mais enxutos. A engine continua se concentrando em um núcleo menor. Câmeras, UI do jogo, importação de OBJ, salvamento e visuais do Windows agora têm seus próprios repositórios de bricks. Neste mês, a localização também saiu do núcleo e do renderizador para um brick próprio. Bricks podem declarar os pacotes NuGet de que precisam, como faz o backend Bepu, e depender de fontes fixadas em um commit Git ou no checksum de um arquivo compactado.

Guinevere da versão 5.7 à 6.5
O Studio é desenhado pelo Guinevere, então boa parte do que você acabou de ler é trabalho no Guinevere. Os lançamentos deste mês foram da versão 5.7 à 6.5. A única quebra de compatibilidade foi na 6.0, base do novo visual do Turian 3.0:
- Estilização. Material 3 é o padrão dos controles Excalibur; o visual anterior continua disponível como
ExcaliburStyles.Classic. As folhas de estilo viraram arquivos.pssno pacote próprioMASS4.Guinevere.Styling, com expressões de valores, funções de cores do tema, esquema de cores e cor de destaque do sistema, sombras e brilho de texto e fundos bitmap e de nove fatias. - Desenho na GPU. As integrações Silk.NET, OpenTK e Raylib desenham com Skia na GPU, mantendo a CPU como alternativa. Todas renderizam sob demanda por padrão.
- Animação. Molas e tweens identificados por chave, transições de propriedades e mudanças de estado animadas.
- Efeitos de renderização. Pilhas ordenadas de efeitos são aplicadas a um painel inteiro, incluindo texto, formas e imagens. Treze filtros integrados cobrem desfoque, brilho, sombras, ajustes de cor, pixelização, separação cromática e nitidez, configuráveis em C# ou
.pss. - Um editor de código. O novo pacote TextEditor é um editor virtualizado de código-fonte e shaders com múltiplos cursores, seleção retangular, recolhimento de blocos, busca e substituição, autocompletar, documentação ao passar o cursor e diagnósticos em segundo plano. Ele lida normalmente com arquivos de 100.000 linhas.
- Texto. Texto rico com trechos estilizados, links e imagens em linha; um controle Markdown com atualização incremental e blocos de código com destaque de sintaxe; controles tipográficos (espaçamento, tabulações, justificação, kerning) e modelagem opcional de texto para ligaturas e marcas combinantes. Os layouts de texto agora ficam em cache e são compartilhados entre medição e desenho.
- Grafos. O novo pacote
MASS4.Guinevere.Graphsé um editor de grafos de nós: nós, portas e conexões em uma tela com deslocamento e zoom, seleção retangular, grupos recolhíveis, copiar e colar, desfazer, minimapa e estilização via.pss. É totalmente operável pelo teclado e, no Linux, comunica-se com leitores de tela por uma nova ponte de acessibilidade do desktop. - Jogos, controles e toque. Navegação de foco por controle, ações semânticas de controle, multitoque com gestos opcionais, viewports com área segura para celulares e primitivas de HUD para a UI do jogo.
- Detalhes menores. Um seletor de cores feito de peças substituíveis, uma lista suspensa pesquisável com seleção múltipla, editores de enum que reconhecem flags e abas encaixáveis que mostram onde serão posicionadas.

Com a sua ajuda
Há muitas outras correções, ajustes e melhorias que não foram listados aqui. A lista completa está no changelog. A documentação cobre bricks, renderização, gizmos e temas. Se algo quebrar, me avise no GitHub. Se quiser ajudar a financiar o próximo lançamento, você me encontra no Patreon ou no Ko-fi.
#release#engine#studio#physics#dotnet