Skip to content

Capitolo 6.4: Sistema telecamere ​


Introduzione ​

DayZ utilizza un sistema telecamere multilivello. La telecamera del giocatore viene gestita dal motore tramite le sottoclassi di DayZPlayerCamera. Per il modding e il debug, la FreeDebugCamera consente il volo libero. Il motore fornisce anche accessori globali per lo stato corrente della telecamera. Questo capitolo tratta i tipi di telecamera, come accedere ai dati della telecamera e come utilizzare gli strumenti telecamera scriptati.


Stato attuale della telecamera (Accessori globali) ​

Questi metodi sono disponibili ovunque e restituiscono lo stato della telecamera attiva indipendentemente dal tipo di telecamera:

c
// Posizione mondiale attuale della telecamera
proto native vector GetGame().GetCurrentCameraPosition();

// Direzione in avanti della telecamera attuale (vettore unitario)
proto native vector GetGame().GetCurrentCameraDirection();

// Conversione posizione mondiale in coordinate schermo
proto native vector GetGame().GetScreenPos(vector world_pos);
// Restituisce: x = schermo X (pixel), y = schermo Y (pixel), z = profondita (distanza dalla telecamera)

Esempio --- verificare se una posizione e sullo schermo:

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

    // z < 0 significa dietro la telecamera
    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);
}

Esempio --- ottenere la distanza dalla telecamera a un punto:

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

Sistema DayZPlayerCamera ​

Le telecamere dei giocatori DayZ sono classi native gestite dal controller del giocatore del motore. Non vengono istanziate direttamente dallo script --- invece, il motore seleziona la telecamera appropriata in base allo stato del giocatore (in piedi, prono, nuoto, veicolo, incosciente, ecc.).

Tipi di telecamera (Costanti DayZPlayerCameras) ​

Gli ID dei tipi di telecamera sono definiti come costanti:

CostanteDescrizione
DayZPlayerCameras.DAYZCAMERA_1STTelecamera in prima persona
DayZPlayerCameras.DAYZCAMERA_3RD_ERCTerza persona in piedi
DayZPlayerCameras.DAYZCAMERA_3RD_CROTerza persona accovacciato
DayZPlayerCameras.DAYZCAMERA_3RD_PROTerza persona prono
DayZPlayerCameras.DAYZCAMERA_3RD_ERC_SPRTerza persona sprint
DayZPlayerCameras.DAYZCAMERA_3RD_ERC_RAISEDTerza persona arma alzata
DayZPlayerCameras.DAYZCAMERA_3RD_CRO_RAISEDTerza persona accovacciato arma alzata
DayZPlayerCameras.DAYZCAMERA_IRONSIGHTSMira con tacca di mira
DayZPlayerCameras.DAYZCAMERA_OPTICSMira con ottica/cannocchiale
DayZPlayerCameras.DAYZCAMERA_3RD_VEHICLETerza persona veicolo
DayZPlayerCameras.DAYZCAMERA_1ST_VEHICLEPrima persona veicolo
DayZPlayerCameras.DAYZCAMERA_1ST_UNCONSCIOUSPrima persona incosciente
DayZPlayerCameras.DAYZCAMERA_3RD_CLIMBTerza persona arrampicata
DayZPlayerCameras.DAYZCAMERA_3RD_JUMPTerza persona salto

Ottenere il tipo di telecamera attuale ​

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

FreeDebugCamera ​

File: 3_Game/entities/camera.c

La telecamera a volo libero utilizzata per il debug e il lavoro cinematografico. Disponibile nelle build diagnostiche o quando abilitata dai mod.

Accesso all'istanza ​

c
static proto native FreeDebugCamera GetInstance();

Questo metodo statico restituisce l'istanza singleton della telecamera libera (o null se non esiste). Chiamalo come FreeDebugCamera.GetInstance().

Metodi principali ​

c
// Abilitare/disabilitare la telecamera libera (ereditato da Camera)
proto native void SetActive(bool active);
proto native bool IsActive();

// Posizione e orientamento
vector GetPosition();
void   SetPosition(vector pos);
vector GetOrientation();
void   SetOrientation(vector ori);   // imbardata, beccheggio, rollio

// Direzione della telecamera
vector GetDirection();

Esempio --- attivare la telecamera libera e teletrasportarla:

c
void ActivateDebugCamera(vector pos)
{
    FreeDebugCamera cam = FreeDebugCamera.GetInstance();
    if (cam)
    {
        cam.SetActive(true);
        cam.SetPosition(pos);
        cam.SetOrientation(Vector(0, -30, 0));  // Guarda leggermente verso il basso
    }
}

Campo visivo (FOV) ​

Il motore controlla il FOV nativamente. Puoi leggerlo e modificarlo tramite il sistema telecamera del giocatore:

Lettura del FOV ​

c
// Ottenere il FOV della telecamera attuale (in radianti)
float fov = Camera.GetCurrentFOV();

Override del FOV in DayZPlayerCamera ​

Nelle classi telecamera personalizzate che estendono DayZPlayerCamera, puoi sovrascrivere il FOV:

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

Profondita di campo (DOF) ​

La profondita di campo e controllata tramite il sistema di effetti di post-elaborazione (vedi Capitolo 6.5). Tuttavia, il sistema telecamera lavora con il DOF attraverso questi meccanismi:

Impostazione del DOF tramite CGame ​

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

Disabilitazione del DOF ​

c
GetGame().OverrideDOF(false, 0, 0, 0, 0, 1);  // Il primo argomento false disabilita il DOF

ScriptCamera (GameLib) ​

File: 2_GameLib/entities/scriptcamera.c

Un'entita telecamera scriptata di livello inferiore dal layer GameLib. Questa e la base per le implementazioni di telecamere personalizzate.

Creazione di una telecamera ​

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

Metodi principali ​

Nota: ScriptCamera viene compilato solo sotto #ifdef GAME_TEMPLATE e non e presente nella build del gioco DayZ. Si configura tramite i metodi telecamera di GenericEntity (SetCameraVerticalFOV, SetCameraNearPlane, SetCameraFarPlane, SetCameraType). I metodi seguenti appartengono alla classe del motore Camera (3_Game/entities/camera.c), che FreeDebugCamera estende:

c
proto native void SetFOV(float fov);                 // FOV in radianti
proto native void SetNearPlane(float nearPlane);     // limitato internamente a 0.01m
proto native float GetNearPlane();
proto native void SetFocus(float distance, float blur);  // profondita di campo

Attivazione di una telecamera ​

c
// Rendere questa telecamera la telecamera di rendering attiva
GetGame().SelectPlayer(null, null);   // Scollegare dal giocatore
GetGame().ObjectRelease(camera);      // Rilasciare al motore

Nota: Passare dalla telecamera del giocatore richiede una gestione attenta dell'input e dell'HUD. La maggior parte dei mod utilizza la telecamera di debug libera o gli effetti overlay PPE invece di creare telecamere personalizzate.


Raycasting dalla telecamera ​

Un pattern comune e il raycasting dalla posizione della telecamera nella direzione della telecamera per trovare cio che il giocatore sta guardando:

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;
}

ConcettoPunto chiave
Accessori globaliGetCurrentCameraPosition(), GetCurrentCameraDirection(), GetScreenPos()
Tipi di telecameraCostanti DayZPlayerCameras (1ST, 3RD_ERC, IRONSIGHTS, OPTICS, VEHICLE, ecc.)
Tipo attualeplayer.GetCurrentCamera().GetCameraName()
Telecamera liberaFreeDebugCamera.GetInstance(), poi cam.SetActive(true)
FOVCamera.GetCurrentFOV() per leggere, impostare pOutResult.m_fFovAbsolute in OnUpdate
DOFGetGame().OverrideDOF(enable, focusDist, focusLen, focusLenNear, blur, offset)
Conversione schermoGetScreenPos(worldPos) restituisce pixel XY + profondita Z

Buone pratiche ​

  • Memorizza nella cache la posizione della telecamera quando la interroghi piu volte per frame. GetGame().GetCurrentCameraPosition() e GetCurrentCameraDirection() sono chiamate al motore --- memorizza il risultato in una variabile locale se ne hai bisogno in piu calcoli nello stesso frame.
  • Usa il controllo di profondita di GetScreenPos() prima del posizionamento dell'UI. Verifica sempre che screenPos[2] > 0 (davanti alla telecamera) prima di disegnare marcatori HUD alle posizioni mondiali, altrimenti i marcatori appariranno specchiati dietro al giocatore.
  • Evita di creare istanze ScriptCamera personalizzate per effetti semplici. La FreeDebugCamera e il sistema PPE coprono la maggior parte delle esigenze cinematografiche e visive. Le telecamere personalizzate richiedono una gestione attenta di input/HUD che e facile da rompere.
  • Rispetta le transizioni dei tipi di telecamera del motore. Non forzare cambi di tipo telecamera dallo script a meno che non gestisci completamente lo stato del controller del giocatore. Cambi di telecamera inaspettati possono bloccare il movimento del giocatore o causare desync.
  • Proteggi l'uso della telecamera libera con controlli admin/debug. La FreeDebugCamera fornisce un'ispezione del mondo simile a quella di un dio. Abilitala solo per admin autenticati o build diagnostiche per prevenire abusi.

Compatibilita e impatto ​

  • Multi-Mod: Gli accessori telecamera sono globali di sola lettura, quindi piu mod possono leggere in sicurezza lo stato della telecamera simultaneamente. I conflitti sorgono solo se due mod tentano entrambi di attivare FreeDebugCamera o istanze ScriptCamera personalizzate.
  • Prestazioni: GetScreenPos() e GetCurrentCameraPosition() sono chiamate leggere al motore. Il raycasting dalla telecamera (DayZPhysics.RaycastRV) e piu costoso --- limitalo a una volta per frame, non per entita.
  • Server/Client: Lo stato della telecamera esiste solo sul client. Tutti i metodi telecamera restituiscono dati privi di significato su un server dedicato. Non usare mai query telecamera nella logica lato server.

<< Precedente: Meteo | Telecamere | Successivo: Effetti di post-elaborazione >>

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