Unity 6000.5: A Mudança Radical de InstanceID para EntityId
O Unity 6000.5 substitui o int instanceID pela nova struct EntityId em toda a API. Veja cada renomeação, a pegadinha de semântica e a correção necessária para compilar sem erros.
Introdução
Toda atualização grande do Unity vem com um ritual conhecido: você clica em Upgrade, espera o reimport e depois vê o Console encher de erros CS0619 em vermelho. Atualizar um projeto real em produção para o Unity 6000.5.7f1 não foi diferente — mas dessa vez, quase todo erro tinha a mesma causa raiz: o Unity substituiu silenciosamente o int instanceID por uma nova struct chamada EntityId em uma parte enorme da API pública.
Isso não é um método obsoleto isolado aqui e ali. É uma mudança de tipo em nÃvel de engine que afeta GameObject, Object, EditorUtility, EditorApplication e qualquer código seu que armazene ou compare instance IDs. Se você mantém um projeto com assets de terceiros ou ferramentas próprias de Editor, essa é a mudança que vai consumir mais do seu tempo — por isso este post é focado inteiramente nela.
Todas as correções abaixo são substituições 1:1. Nada aqui muda o comportamento do seu jogo — só move o código para a API atual, não obsoleta.
O Problema: int instanceID Está Sendo SubstituÃdo por EntityId
Historicamente, todo UnityEngine.Object expunha GetInstanceID(), retornando um int simples que identificava o objeto de forma única durante aquela sessão. O Unity 6000.5 introduz o EntityId, uma struct leve que substitui o int como o tipo canônico de identificador em toda a API do Editor e de runtime. Os membros antigos baseados em int ainda existem por enquanto, mas estão marcados como obsoletos e — no caso deste projeto — configurados para gerar um erro CS0619 completo, não apenas um warning:
error CS0619: 'EditorApplication.hierarchyWindowItemOnGUI' is obsolete:
'Use hierarchyWindowItemByEntityIdOnGUI instead. (UnityUpgradable)'
Assim que um script usa a API antiga, o projeto inteiro deixa de compilar — inclusive o Play Mode. Aqui está o conjunto completo de renomeações que precisei aplicar.
Correção 1: GetInstanceID() → GetEntityId()
A mudança mais comum. Qualquer código que pegava um ID numérico de um GameObject, Material ou outro Object precisa trocar para o novo acessor:
// Antes
int uniqueId = sourceObject.GetInstanceID();
// Depois
EntityId uniqueId = sourceObject.GetEntityId();
Isso também significa que todo Dictionary<int, T> ou Dictionary<int, List<T>> indexado por instance ID precisa ter o tipo da chave atualizado:
// Antes
private Dictionary<int, List<GameObject>> instantiatedObjects = new Dictionary<int, List<GameObject>>();
private Dictionary<int, int> poolCursors = new Dictionary<int, int>();
// Depois
private Dictionary<EntityId, List<GameObject>> instantiatedObjects = new Dictionary<EntityId, List<GameObject>>();
private Dictionary<EntityId, int> poolCursors = new Dictionary<EntityId, int>();
O EntityId implementa igualdade e hashing corretamente, então ele funciona como chave de Dictionary exatamente como o int funcionava — sem mudança de comportamento, apenas troca de tipo.
Correção 2: EditorUtility.InstanceIDToObject → EntityIdToObject
Ferramentas de Editor que resolvem um objeto de volta a partir do seu ID precisam do método de busca correspondente:
// Antes
GameObject gameObject = EditorUtility.InstanceIDToObject(instanceID) as GameObject;
// Depois
GameObject gameObject = EditorUtility.EntityIdToObject(entityId) as GameObject;
Correção 3: Callbacks da Janela de Hierarquia
Se você desenha Ãcones ou overlays customizados na janela Hierarchy, o tipo do delegate e o próprio evento foram renomeados:
// Antes
private static readonly EditorApplication.HierarchyWindowItemCallback callback;
static MyTool()
{
callback = new EditorApplication.HierarchyWindowItemCallback(DrawIcon);
EditorApplication.hierarchyWindowItemOnGUI =
(EditorApplication.HierarchyWindowItemCallback)Delegate.Combine(
EditorApplication.hierarchyWindowItemOnGUI, callback);
}
private static void DrawIcon(int instanceID, Rect selectionRect) { /* ... */ }
// Depois
private static readonly EditorApplication.HierarchyWindowItemByEntityIdCallback callback;
static MyTool()
{
callback = new EditorApplication.HierarchyWindowItemByEntityIdCallback(DrawIcon);
EditorApplication.hierarchyWindowItemByEntityIdOnGUI =
(EditorApplication.HierarchyWindowItemByEntityIdCallback)Delegate.Combine(
EditorApplication.hierarchyWindowItemByEntityIdOnGUI, callback);
}
private static void DrawIcon(EntityId entityId, Rect selectionRect) { /* ... */ }
O mesmo padrão vale para inscrever/desinscrever com += / -= em outras partes do seu código de Editor — basta trocar hierarchyWindowItemOnGUI por hierarchyWindowItemByEntityIdOnGUI.
Correção 4: A Pegadinha de Semântica — EntityId Não Tem Valores Negativos
Essa é a pegadinha que não aparece como erro de compilação, só como um bug de comportamento silencioso. Muito código Unity mais antigo usava uma convenção simples: instance IDs negativos significam que o objeto existe só em memória (criado em tempo de execução, não salvo como asset), enquanto IDs positivos significam um asset persistente. Código dependia disso para decidir coisas como "devo duplicar esse material" ou "isso é uma instância de cena ou um asset de prefab":
// Antes – depende do sinal do int
instanceID = GetInstanceID();
if (instanceID < 0)
{
DuplicateMaskedMaterials();
}
O EntityId não carrega essa convenção de sinal — todos os seus valores se comportam como identificadores sem sinal, então comparações < 0 deixam de fazer sentido. A substituição correta é perguntar diretamente ao Editor se o objeto é um asset persistente:
// Depois – intenção explÃcita em vez de depender do sinal do ID
instanceID = GetEntityId();
if (!EditorUtility.IsPersistent(this))
{
DuplicateMaskedMaterials();
}
Também preste atenção na checagem de "ainda não inicializado". O código costumava comparar com 0:
// Antes
if (instanceID == 0) { instanceID = GetInstanceID(); }
// Depois
if (!instanceID.IsValid()) { instanceID = GetEntityId(); }
🛑 Por que isso importa mais que as renomeações
Uma renomeação que não compila é uma correção de cinco minutos. Uma checagem baseada em sinal que para de funcionar silenciosamente é um bug que só aparece depois — por exemplo, materiais que deixam de ser duplicados corretamente para objetos criados em tempo de execução. Se o seu projeto tem qualquer lógica do tipo `instanceID < 0` ou `instanceID > 0`, audite especificamente esses pontos; não assuma que um simples find-and-replace do nome do método é suficiente.
Correção 5: Campos int instanceID Serializados
Se um MonoBehaviour serializa um instance ID para detectar duplicação (um truque comum para lógica do tipo "esse objeto foi clonado desde a última vez que verifiquei"), o próprio tipo do campo precisa mudar:
// Antes
[SerializeField]
int instanceID = 0;
// Depois
[SerializeField]
EntityId instanceID;
EntityId é uma struct serializável, então essa é uma troca direta de tipo de campo — o Unity cuida da serialização para você.
Um Padrão Mais Amplo: Obsoleto-como-Erro é a Nova Norma
Além do EntityId, essa atualização também sinalizou outras APIs da engine que antes eram "obsoletas suaves" (um warning CS0618) e agora são erros obrigatórios sob as configurações de analisador do Unity 6000.5 — por exemplo, HierarchyProperty (substituÃdo por HierarchyIterator, ou por SceneManager.GetRootGameObjects() no caso comum de "enumerar raÃzes da cena") e MaterialProperty.type (substituÃdo por MaterialProperty.propertyType, retornando ShaderPropertyType). A lição se generaliza: trate todo CS0619 como um bloqueador obrigatório, não como algo para silenciar com um pragma, porque o Unity está visivelmente caminhando para tornar APIs obsoletas inegociáveis, e não apenas desencorajadas.
Um Checklist Prático para a Migração do EntityId
- Busque no projeto por
GetInstanceID(),InstanceIDToObject,hierarchyWindowItemOnGUIeDictionary<int,— esses são os padrões com maior taxa de ocorrência. - Para todo
intserializado que armazena um instance ID, troque o tipo do campo paraEntityId. - Audite qualquer comparação
< 0/> 0/== 0em um instance ID antigo — elas codificam suposições que não valem mais paraEntityIde precisam deIsValid()/EditorUtility.IsPersistent()no lugar. - Atualize os tipos de chave de
Dictionary/HashSetdeintparaEntityIdsempre que eram indexados por instance ID. - Rode um build completo (não só o Play Mode) depois que o Console estiver limpo — alguns desses caminhos só executam durante um build ou em modo batch.
Conclusão
A migração para EntityId no Unity 6000.5 é o tipo de mudança que parece uma simples renomeação até você esbarrar na pegadinha da comparação de sinal — e é essa parte que vale a pena lembrar, não só a sintaxe. GetInstanceID() → GetEntityId(), InstanceIDToObject → EntityIdToObject, hierarchyWindowItemOnGUI → hierarchyWindowItemByEntityIdOnGUI, e id < 0 → !EditorUtility.IsPersistent(this) foram suficientes para deixar um projeto real em produção compilando e se comportando corretamente de novo no Unity 6000.5.7f1.
Se você estiver enfrentando um erro especÃfico relacionado ao EntityId que não está coberto aqui, deixe um comentário ou entre em contato — terei prazer em ajudar a encontrar a correção.
Perguntas frequentes
Por que meu projeto Unity para de compilar após atualizar para o Unity 6000.5 com um erro CS0619 mencionando EntityId?
O Unity 6000.5 substituiu a antiga API GetInstanceID baseada em int por uma nova struct chamada EntityId. Qualquer código que ainda chame os membros antigos baseados em int agora gera um erro de compilação CS0619 obrigatório em vez de um warning, e um único script com esse problema trava a compilação do projeto inteiro, inclusive o Play Mode.
O que substitui o GetInstanceID() no Unity 6000.5?
Use GetEntityId(), que retorna a nova struct EntityId em vez de um int simples. Qualquer Dictionary ou HashSet que antes usava int como chave também deve ser atualizado para EntityId, já que ela implementa igualdade e hashing da mesma forma.
Por que meu código com "if (instanceID < 0)" para de funcionar corretamente depois de trocar para EntityId?
O EntityId não segue a antiga convenção de sinal, em que um valor negativo indicava um objeto que só existia em memória. Substitua checagens baseadas em sinal por EditorUtility.IsPersistent(this) para determinar se um objeto é um asset salvo, em vez de depender do sinal do identificador.
O HierarchyProperty também foi removido no Unity 6000.5?
O HierarchyProperty está marcado como obsoleto e, nas configurações de analisador deste projeto, também gera erro de compilação. Use o HierarchyIterator, ou o SceneManager.GetRootGameObjects() para o caso comum de enumerar objetos raiz nas cenas carregadas.
Preciso corrigir manualmente cada asset de terceiros para o Unity 6000.5?
Verifique primeiro se existe uma versão mais nova na Asset Store ou no Package Manager, já que a maioria dos autores de plugins lança versões compatíveis com o Unity 6 rapidamente. Só corrija o código-fonte diretamente, seguindo as renomeações deste guia, quando não houver uma versão atualizada disponível ainda.
Comentários
Ficou com uma dúvida ou encontrou um problema no código? Comente abaixo — eu leio e respondo pessoalmente.