Skip to content

Capítulo 6.4: Sistema de Cámaras ​


Introducción ​

DayZ utiliza un sistema de cámaras multicapa. La cámara del jugador es gestionada por el motor a través de subclases de DayZPlayerCamera. Para modding y depuración, la FreeDebugCamera permite vuelo libre. El motor también proporciona accesores globales para el estado actual de la cámara. Este capítulo cubre los tipos de cámara, cómo acceder a los datos de la cámara y cómo usar las herramientas de cámara por script.


Estado Actual de la Cámara (Accesores Globales) ​

Estos métodos están disponibles en cualquier lugar y devuelven el estado de la cámara activa independientemente del tipo de cámara:

c
// Posición mundial actual de la cámara
proto native vector GetGame().GetCurrentCameraPosition();

// Dirección frontal actual de la cámara (vector unitario)
proto native vector GetGame().GetCurrentCameraDirection();

// Convertir posición mundial a coordenadas de pantalla
proto native vector GetGame().GetScreenPos(vector world_pos);
// Retorna: x = X de pantalla (píxeles), y = Y de pantalla (píxeles), z = profundidad (distancia desde la cámara)

Ejemplo --- verificar si una posición está en pantalla:

c
bool IsPositionOnScreen(vector worldPos)
{
    vector screenPos = GetGame().GetScreenPos(worldPos);

    // z < 0 significa detrás de la cámara
    if (screenPos[2] < 0)
        return false;

    int screenW, screenH;
    GetScreenSize(screenW, screenH);

    return (screenPos[0] >= 0 && screenPos[0] <= screenW &&
            screenPos[1] >= 0 && screenPos[1] <= screenH);
}

Ejemplo --- obtener distancia desde la cámara a un punto:

c
float DistanceFromCamera(vector worldPos)
{
    return vector.Distance(GetGame().GetCurrentCameraPosition(), worldPos);
}

Sistema DayZPlayerCamera ​

Las cámaras del jugador en DayZ son clases nativas gestionadas por el controlador del jugador del motor. No se instancian directamente desde script --- en su lugar, el motor selecciona la cámara apropiada según el estado del jugador (de pie, tumbado, nadando, en vehículo, inconsciente, etc.).

Tipos de Cámara (Constantes de DayZPlayerCameras) ​

Los IDs de tipo de cámara se definen como constantes:

ConstanteDescripción
DayZPlayerCameras.DAYZCAMERA_1STCámara en primera persona
DayZPlayerCameras.DAYZCAMERA_3RD_ERCTercera persona erguido (de pie)
DayZPlayerCameras.DAYZCAMERA_3RD_CROTercera persona agachado
DayZPlayerCameras.DAYZCAMERA_3RD_PROTercera persona tumbado
DayZPlayerCameras.DAYZCAMERA_3RD_ERC_SPRTercera persona corriendo
DayZPlayerCameras.DAYZCAMERA_3RD_ERC_RAISEDTercera persona arma levantada
DayZPlayerCameras.DAYZCAMERA_3RD_CRO_RAISEDTercera persona agachado arma levantada
DayZPlayerCameras.DAYZCAMERA_IRONSIGHTSApuntando con mira de hierro
DayZPlayerCameras.DAYZCAMERA_OPTICSApuntando con óptica/mira
DayZPlayerCameras.DAYZCAMERA_3RD_VEHICLETercera persona en vehículo
DayZPlayerCameras.DAYZCAMERA_1ST_VEHICLEPrimera persona en vehículo
DayZPlayerCameras.DAYZCAMERA_1ST_UNCONSCIOUSPrimera persona inconsciente
DayZPlayerCameras.DAYZCAMERA_3RD_CLIMBTercera persona escalando
DayZPlayerCameras.DAYZCAMERA_3RD_JUMPTercera persona saltando

Obtener el Tipo de Cámara Actual ​

c
DayZPlayer player = GetGame().GetPlayer();
if (player)
{
    DayZPlayerCamera cam = player.GetCurrentCamera();
    if (cam && cam.GetCameraName() == "DayZPlayerCamera1stPerson")
    {
        Print("Player is in first person");
    }
}

FreeDebugCamera ​

Archivo: 3_Game/entities/camera.c

La cámara de vuelo libre utilizada para depuración y trabajo cinemático. Disponible en compilaciones de diagnóstico o cuando es habilitada por mods.

Acceder a la Instancia ​

c
static proto native FreeDebugCamera GetInstance();

Este método estático retorna la instancia singleton de la cámara libre (o null si no existe). Llámalo como FreeDebugCamera.GetInstance().

Métodos Principales ​

c
// Habilitar/deshabilitar la cámara libre (heredado de Camera)
proto native void SetActive(bool active);
proto native bool IsActive();

// Posición y orientación
vector GetPosition();
void   SetPosition(vector pos);
vector GetOrientation();
void   SetOrientation(vector ori);   // yaw, pitch, roll

// Dirección de la cámara
vector GetDirection();

Ejemplo --- activar cámara libre y teletransportarla:

c
void ActivateDebugCamera(vector pos)
{
    FreeDebugCamera cam = FreeDebugCamera.GetInstance();
    if (cam)
    {
        cam.SetActive(true);
        cam.SetPosition(pos);
        cam.SetOrientation(Vector(0, -30, 0));  // Mirar ligeramente hacia abajo
    }
}

Campo de Visión (FOV) ​

El motor controla el FOV de forma nativa. Puedes leerlo y modificarlo a través del sistema de cámara del jugador:

Leer el FOV ​

c
// Obtener el FOV actual de la cámara (en radianes)
float fov = Camera.GetCurrentFOV();

Sobreescritura de FOV en DayZPlayerCamera ​

En clases de cámara personalizadas que extienden DayZPlayerCamera, puedes sobreescribir el FOV:

c
class MyCustomCamera extends DayZPlayerCamera1stPerson
{
    override void OnUpdate(float pDt, out DayZPlayerCameraResult pOutResult)
    {
        super.OnUpdate(pDt, pOutResult);
        pOutResult.m_fFovAbsolute = 0.7854;  // ~45 grados (radianes)
    }
}

Profundidad de Campo (DOF) ​

La profundidad de campo se controla a través del sistema de Efectos de Post-Procesado (ver Capítulo 6.5). Sin embargo, el sistema de cámaras trabaja con DOF mediante estos mecanismos:

Configurar DOF vía CGame ​

c
// OverrideDOF(enable, focusDistance, focusLength, focusLengthNear, blur, focusDepthOffset)
GetGame().OverrideDOF(true, 5.0, 100.0, 0.5, 0.3, 0.0);

Deshabilitar DOF ​

c
GetGame().OverrideDOF(false, 0, 0, 0, 0, 1);  // El primer argumento false deshabilita DOF

ScriptCamera (GameLib) ​

Archivo: 2_GameLib/entities/scriptcamera.c

Una entidad de cámara con script de nivel más bajo de la capa GameLib. Esta es la base para implementaciones de cámara personalizadas.

Crear una Cámara ​

c
ScriptCamera camera = ScriptCamera.Cast(
    GetGame().CreateObject("ScriptCamera", pos, true)  // solo local
);

Métodos Principales ​

Nota: ScriptCamera se compila únicamente bajo #ifdef GAME_TEMPLATE y no está presente en la compilación del juego DayZ. Se configura a sí misma a través de los métodos de cámara de GenericEntity (SetCameraVerticalFOV, SetCameraNearPlane, SetCameraFarPlane, SetCameraType). Los métodos siguientes pertenecen a la clase de motor Camera (3_Game/entities/camera.c), de la cual FreeDebugCamera hereda:

c
proto native void SetFOV(float fov);                 // FOV en radianes
proto native void SetNearPlane(float nearPlane);     // limitado internamente a 0.01m
proto native float GetNearPlane();
proto native void SetFocus(float distance, float blur);  // profundidad de campo

Activar una Cámara ​

c
// Hacer que esta cámara sea la cámara de renderizado activa
GetGame().SelectPlayer(null, null);   // Desacoplar del jugador
GetGame().ObjectRelease(camera);      // Liberar al motor

Nota: Cambiar de la cámara del jugador requiere un manejo cuidadoso del input y el HUD. La mayoría de los mods usan la cámara libre de depuración o efectos de overlay PPE en lugar de crear cámaras personalizadas.


Raycasting desde la Cámara ​

Un patrón común es hacer raycast desde la posición de la cámara en la dirección de la cámara para encontrar qué está mirando el jugador:

c
Object GetObjectInCrosshair(float maxDistance)
{
    vector from = GetGame().GetCurrentCameraPosition();
    vector to = from + (GetGame().GetCurrentCameraDirection() * maxDistance);

    vector contactPos;
    vector contactDir;
    int contactComponent;
    set<Object> hitObjects = new set<Object>;

    if (DayZPhysics.RaycastRV(from, to, contactPos, contactDir,
                               contactComponent, hitObjects, null, null,
                               false, false, ObjIntersectView, 0.0))
    {
        if (hitObjects.Count() > 0)
            return hitObjects[0];
    }

    return null;
}

Resumen ​

ConceptoPunto Clave
Accesores globalesGetCurrentCameraPosition(), GetCurrentCameraDirection(), GetScreenPos()
Tipos de cámaraConstantes de DayZPlayerCameras (1ST, 3RD_ERC, IRONSIGHTS, OPTICS, VEHICLE, etc.)
Tipo actualplayer.GetCurrentCamera().GetCameraName()
Cámara libreFreeDebugCamera.GetInstance(), luego cam.SetActive(true)
FOVCamera.GetCurrentFOV() para leer, establecer pOutResult.m_fFovAbsolute en OnUpdate
DOFGetGame().OverrideDOF(enable, focusDist, focusLen, focusLenNear, blur, offset)
Conversión de pantallaGetScreenPos(worldPos) retorna XY en píxeles + profundidad Z

Mejores Prácticas ​

  • Almacena en caché la posición de la cámara cuando la consultes múltiples veces por frame. GetGame().GetCurrentCameraPosition() y GetCurrentCameraDirection() son llamadas al motor --- guarda el resultado en una variable local si lo necesitas en múltiples cálculos dentro del mismo frame.
  • Usa la verificación de profundidad de GetScreenPos() antes de colocar UI. Siempre verifica que screenPos[2] > 0 (delante de la cámara) antes de dibujar marcadores HUD en posiciones del mundo, o los marcadores aparecerán reflejados detrás del jugador.
  • Evita crear instancias de ScriptCamera personalizadas para efectos simples. La FreeDebugCamera y el sistema PPE cubren la mayoría de las necesidades cinemáticas y visuales. Las cámaras personalizadas requieren un manejo cuidadoso del input/HUD que es fácil de romper.
  • Respeta las transiciones de tipo de cámara del motor. No fuerces cambios de tipo de cámara desde script a menos que manejes completamente el estado del controlador del jugador. Cambios inesperados de cámara pueden bloquear el movimiento del jugador o causar desincronización.
  • Protege el uso de la cámara libre detrás de verificaciones de admin/depuración. FreeDebugCamera proporciona inspección del mundo con capacidades de dios. Solo habilítala para administradores autenticados o compilaciones de diagnóstico para prevenir abuso.

Compatibilidad e Impacto ​

  • Multi-Mod: Los accesores de cámara son globales de solo lectura, por lo que múltiples mods pueden leer el estado de la cámara simultáneamente de forma segura. Los conflictos surgen solo si dos mods intentan activar FreeDebugCamera o instancias de ScriptCamera personalizadas al mismo tiempo.
  • Rendimiento: GetScreenPos() y GetCurrentCameraPosition() son llamadas ligeras al motor. El raycasting desde la cámara (DayZPhysics.RaycastRV) es más costoso --- limítalo a una vez por frame, no por entidad.
  • Servidor/Cliente: El estado de la cámara existe solo en el cliente. Todos los métodos de cámara devuelven datos sin sentido en un servidor dedicado. Nunca uses consultas de cámara en lógica del lado del servidor.

<< Anterior: Clima | Cámaras | Siguiente: Efectos de Post-Procesado >>

Released under CC BY-SA 4.0 | Code examples under MIT License