Instanciar y destruir objetos
Crea objetos de red dinámicos y controla correctamente su ciclo de vida.
Instanciar y destruir objetos
Los objetos dinámicos aparecen durante la ejecución y deben ser conocidos por el servidor y por los clientes que participan en su canal. Eco proporciona métodos de conveniencia desde Componente y Eco para solicitar su creación y destrucción.
Idea principal
Instanciar un GameObject de Unity no lo convierte automáticamente en un objeto de red. La creación debe pasar por el flujo de Eco para que el objeto reciba identidad, canal y propietario de red.
Objeto estático frente a dinámico
Eco distingue entre objetos presentes en la escena y objetos creados durante la partida:
| Tipo | Identidad | Ciclo de vida |
|---|---|---|
| Estático | ID persistente de escena | Existe al cargar el nivel |
| Dinámico | ID asignado durante la ejecución | Se crea y destruye durante la sesión |
Los IDs estáticos están en el rango 1–32767. Los dinámicos comienzan en 32768. https://github.com/Nervelink/eco/blob/main/src/Assets/Pandora/Logica/Nucleo/Core/Red/Cliente/Objeto.cs
Requisito: prefab registrable
Para instanciar un objeto en red, Eco necesita localizar el recurso que se va a crear. El path utilizado por Instanciar debe corresponder al recurso esperado por la infraestructura de Eco.
El objeto resultante debe incluir un Objeto y los Componente que implementen su comportamiento de red.
Prefab
├── Objeto
├── Componente
└── Componente...Componente puede recuperar automáticamente su Objeto asociado durante su ciclo de inicialización. https://github.com/Nervelink/eco/blob/main/src/Assets/Pandora/Logica/Nucleo/Core/Red/Cliente/Componente.cs
Instanciar desde un componente
Componente proporciona dos sobrecargas de Instantiate que delegan en Eco.Instanciar utilizando el canal del objeto asociado:
Instantiate(rccID, "Unidades/Guerrero", false, datos...);O utilizando el nombre de una función de creación:
Instantiate("CrearGuerrero", "Unidades/Guerrero", false, datos...);El flujo es:
Componente
↓
Instanciar(...)
↓
Eco.Instanciar(...)
↓
solicitud de creación
↓
servidor / canal
↓
objeto dinámicoLa sobrecarga con rccID utiliza un identificador numérico de creación; la otra utiliza un nombre de función. https://github.com/Nervelink/eco/blob/main/src/Assets/Pandora/Logica/Nucleo/Core/Red/Cliente/Componente.cs
Canal de creación
La creación se realiza en el canal del objeto desde el que se solicita:
Instantiate("CrearGuerrero", "Unidades/Guerrero", false);Conceptualmente:
Objeto origen
│
└── channelID = 20
│
▼
Eco.Instanciar
│
▼
Canal 20
│
▼
nuevo ObjetoEsto evita crear accidentalmente una entidad en un canal diferente del contexto de gameplay que la originó.
Persistencia
La llamada de creación recibe un parámetro persistent:
Instantiate("CrearGuerrero", "Unidades/Guerrero", true);La persistencia indica que el objeto forma parte del estado que el servidor debe conservar para futuras restauraciones o participantes, frente a un objeto puramente temporal de la sesión.
La elección debe hacerse por semántica del objeto:
¿Debe existir al restaurar el estado del canal?
│
┌───┴───┐
sí no
│ │
true falseNo utilices persistent = true simplemente porque el objeto deba ser visible para todos; son conceptos diferentes.
Ownership
Un objeto dinámico puede tener propietario. Objeto expone:
objeto.owner
objeto.ownerID
objeto.isMineLos objetos dinámicos permiten transferir la propiedad a un jugador válido del canal o retirarla mediante ownerID = 0. Los objetos estáticos no permiten cambiar su propietario de esta forma. https://github.com/Nervelink/eco/blob/main/src/Assets/Pandora/Logica/Nucleo/Core/Red/Cliente/Objeto.cs
Objeto dinámico
│
├── propietario = Jugador A
│
└── puede transferirseLa propiedad importa porque determinados cambios de estado y operaciones de red dependen de quién tiene autoridad.
Saber cuándo ha terminado la creación
Un Objeto distingue entre estar creado localmente y haber sido registrado por completo:
objeto.hasBeenRegisteredLa propiedad pasa a true cuando finaliza la creación y el objeto recibe su ID de red. Antes de eso, su identidad todavía no está preparada para todas las operaciones de red. https://github.com/Nervelink/eco/blob/main/src/Assets/Pandora/Logica/Nucleo/Core/Red/Cliente/Objeto.cs
Por tanto, un patrón como este es más seguro:
if (objeto.hasBeenRegistered && objeto.PuedeEnviar)
{
// Operación de red.
}Destruir un objeto
Desde un Componente puede utilizarse:
DestroySelf();La llamada delega en el Objeto asociado y solicita la destrucción de la entidad de red. https://github.com/Nervelink/eco/blob/main/src/Assets/Pandora/Logica/Nucleo/Core/Red/Cliente/Componente.cs
También existe una sobrecarga con retraso y control sobre quién puede solicitarla:
DestroySelf(2f, true);El segundo parámetro permite exigir que la operación sólo se ejecute cuando corresponda al propietario.
Destrucción local frente a destrucción de red
No es equivalente hacer:
Destroy(gameObject);a hacer:
DestroySelf();La primera operación sólo actúa directamente sobre el GameObject local. La segunda utiliza la capa de red y permite que la destrucción se propague al resto de participantes y al servidor según el estado de la entidad.
Destroy(gameObject)
↓
solo Unity local
DestroySelf()
↓
Objeto de red
↓
servidor / canal
↓
otros clientesEstado de destrucción
Cuando se solicita la destrucción, Eco marca el objeto inmediatamente como destruido. Esto evita que se sigan enviando RFC entre la solicitud local y la confirmación del servidor. https://github.com/Nervelink/eco/blob/main/src/Assets/Pandora/Logica/Nucleo/Core/Red/Cliente/Objeto.cs
Puede comprobarse mediante:
objeto.hasBeenDestroyedPor eso el estado útil de un objeto dinámico puede visualizarse como:
Creación
↓
Registro pendiente
↓
Registrado
↓
Activo
↓
Destrucción solicitada
↓
DestruidoCallbacks de ciclo de vida
Objeto expone onDestroy para ejecutar lógica antes de las notificaciones normales de OnDestroy de Unity. También expone onTransfer cuando el objeto cambia de canal. https://github.com/Nervelink/eco/blob/main/src/Assets/Pandora/Logica/Nucleo/Core/Red/Cliente/Objeto.cs
Esto permite separar eventos de red de los callbacks generales de Unity.
Evitar instanciación local directa
No es recomendable crear un prefab de red mediante:
Instantiate(prefab);cuando el objeto deba existir para los demás participantes. Esto sólo crea una instancia local y no establece por sí mismo una identidad de red.
El patrón correcto es pasar por el sistema de instanciación de Eco.
Ejemplo completo
Un componente puede crear una unidad y eliminarla posteriormente:
public class GestorUnidades : Componente
{
public void CrearUnidad()
{
Instantiate("CrearUnidad", "Unidades/Guerrero", false, "caballero");
}
public void DestruirUnidad()
{
DestroySelf();
}
}La entidad creada obtiene su propio Objeto, canal, ID dinámico y propietario según las reglas del servidor.
Errores habituales
El prefab existe localmente pero no aparece en otros clientes
Comprueba que estás utilizando Eco.Instanciar o Componente.Instantiate y que el recurso está disponible para la infraestructura de creación. Un Instantiate de Unity por sí solo no registra el objeto en la red.
Intentar enviar inmediatamente después de crear
Comprueba hasBeenRegistered y PuedeEnviar. Durante el registro inicial el objeto puede existir en Unity pero todavía no tener una identidad de red utilizable.
Destruir con Destroy()
Si el objeto es una entidad de red, utiliza DestroySelf() para que la destrucción siga el ciclo de Eco.
Referencias
Objeto
Identidad, ownership y ciclo de vida del objeto de red.
Componente
Comportamiento asociado al objeto y métodos de conveniencia.
TNet
Implementación upstream de referencia histórica.
DeepWiki · TNet
Referencia externa para contrastar la arquitectura heredada.
