Skip to content

第6.4章: カメラシステム ​


はじめに ​

DayZ は多層カメラシステムを使用しています。プレイヤーカメラは DayZPlayerCamera サブクラスを通じてエンジンによって管理されます。Modding やデバッグ用には、FreeDebugCamera で自由飛行が可能です。エンジンは現在のカメラ状態へのグローバルアクセサーも提供しています。この章では、カメラの種類、カメラデータへのアクセス方法、スクリプトカメラツールの使い方を解説します。


現在のカメラ状態(グローバルアクセサー) ​

これらのメソッドはどこからでも利用可能で、カメラの種類に関係なくアクティブなカメラの状態を返します。

c
// 現在のカメラのワールド位置
proto native vector GetGame().GetCurrentCameraPosition();

// 現在のカメラの前方方向(単位ベクトル)
proto native vector GetGame().GetCurrentCameraDirection();

// ワールド座標をスクリーン座標に変換
proto native vector GetGame().GetScreenPos(vector world_pos);
// 戻り値: x = スクリーン X(ピクセル)、y = スクリーン Y(ピクセル)、z = 深度(カメラからの距離)

例 --- 位置が画面上にあるか確認する:

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

    // z < 0 はカメラの背後を意味する
    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);
}

例 --- カメラから地点までの距離を取得する:

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

DayZPlayerCamera システム ​

DayZ のプレイヤーカメラは、エンジンのプレイヤーコントローラーによって管理されるネイティブクラスです。スクリプトから直接インスタンス化されることはありません --- 代わりに、プレイヤーの状態(立ち、伏せ、水泳、車両、意識不明など)に基づいてエンジンが適切なカメラを選択します。

カメラの種類(DayZPlayerCameras 定数) ​

カメラタイプ ID は定数として定義されています。

定数説明
DayZPlayerCameras.DAYZCAMERA_1ST一人称カメラ
DayZPlayerCameras.DAYZCAMERA_3RD_ERC三人称 直立(立ち)
DayZPlayerCameras.DAYZCAMERA_3RD_CRO三人称 しゃがみ
DayZPlayerCameras.DAYZCAMERA_3RD_PRO三人称 伏せ
DayZPlayerCameras.DAYZCAMERA_3RD_ERC_SPR三人称 ダッシュ
DayZPlayerCameras.DAYZCAMERA_3RD_ERC_RAISED三人称 武器構え
DayZPlayerCameras.DAYZCAMERA_3RD_CRO_RAISED三人称 しゃがみ武器構え
DayZPlayerCameras.DAYZCAMERA_IRONSIGHTSアイアンサイト照準
DayZPlayerCameras.DAYZCAMERA_OPTICS光学/スコープ照準
DayZPlayerCameras.DAYZCAMERA_3RD_VEHICLE三人称 車両
DayZPlayerCameras.DAYZCAMERA_1ST_VEHICLE一人称 車両
DayZPlayerCameras.DAYZCAMERA_1ST_UNCONSCIOUS一人称 意識不明
DayZPlayerCameras.DAYZCAMERA_3RD_CLIMB三人称 登攀
DayZPlayerCameras.DAYZCAMERA_3RD_JUMP三人称 ジャンプ

現在のカメラタイプの取得 ​

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

FreeDebugCamera ​

ファイル: 3_Game/entities/camera.c

デバッグやシネマティック作業に使用されるフリーフライトカメラです。診断ビルドまたは Mod で有効にした場合に利用できます。

インスタンスへのアクセス ​

c
static proto native FreeDebugCamera GetInstance();

この静的メソッドはフリーカメラのシングルトンインスタンスを返します(存在しない場合は null)。FreeDebugCamera.GetInstance() として呼び出します。

主要メソッド ​

c
// フリーカメラの有効化/無効化(Camera から継承)
proto native void SetActive(bool active);
proto native bool IsActive();

// 位置と向き
vector GetPosition();
void   SetPosition(vector pos);
vector GetOrientation();
void   SetOrientation(vector ori);   // ヨー、ピッチ、ロール

// カメラの方向
vector GetDirection();

例 --- フリーカメラを有効にしてテレポートする:

c
void ActivateDebugCamera(vector pos)
{
    FreeDebugCamera cam = FreeDebugCamera.GetInstance();
    if (cam)
    {
        cam.SetActive(true);
        cam.SetPosition(pos);
        cam.SetOrientation(Vector(0, -30, 0));  // やや下を見る
    }
}

視野角(FOV) ​

エンジンは FOV をネイティブに制御します。プレイヤーカメラシステムを通じて読み取りや変更が可能です。

FOV の読み取り ​

c
// 現在のカメラ FOV を取得(ラジアン単位)
float fov = Camera.GetCurrentFOV();

DayZPlayerCamera の FOV オーバーライド ​

DayZPlayerCamera を拡張したカスタムカメラクラスでは、FOV をオーバーライドできます。

c
class MyCustomCamera extends DayZPlayerCamera1stPerson
{
    override void OnUpdate(float pDt, out DayZPlayerCameraResult pOutResult)
    {
        super.OnUpdate(pDt, pOutResult);
        pOutResult.m_fFovAbsolute = 0.7854;  // 約45度(ラジアン)
    }
}

被写界深度(DOF) ​

被写界深度はポストプロセスエフェクトシステムを通じて制御されます(第6.5章を参照)。ただし、カメラシステムは以下のメカニズムを通じて DOF と連携します。

CGame を介した DOF の設定 ​

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

DOF の無効化 ​

c
GetGame().OverrideDOF(false, 0, 0, 0, 0, 1);  // 第一引数 false で DOF を無効化

ScriptCamera(GameLib) ​

ファイル: 2_GameLib/entities/scriptcamera.c

GameLib レイヤーの低レベルスクリプトカメラエンティティです。カスタムカメラ実装の基盤となります。

カメラの作成 ​

c
ScriptCamera camera = ScriptCamera.Cast(
    GetGame().CreateObject("ScriptCamera", pos, true)  // ローカルのみ
);

主要メソッド ​

注意: ScriptCamera は #ifdef GAME_TEMPLATE の下でのみコンパイルされ、DayZ のゲームビルドには存在しません。GenericEntity のカメラメソッド(SetCameraVerticalFOV、SetCameraNearPlane、SetCameraFarPlane、SetCameraType)を通じて自身を構成します。以下のメソッドは、FreeDebugCamera が拡張するエンジンの Camera クラス(3_Game/entities/camera.c)に属します。

c
proto native void SetFOV(float fov);                 // ラジアン単位の FOV
proto native void SetNearPlane(float nearPlane);     // 内部的に 0.01m にクランプされる
proto native float GetNearPlane();
proto native void SetFocus(float distance, float blur);  // 被写界深度

カメラのアクティベーション ​

c
// このカメラをアクティブなレンダリングカメラにする
GetGame().SelectPlayer(null, null);   // プレイヤーからデタッチ
GetGame().ObjectRelease(camera);      // エンジンに解放

注意: プレイヤーカメラから切り替える場合、入力や HUD の慎重な処理が必要です。ほとんどの Mod では、カスタムカメラを作成する代わりにフリーデバッグカメラや PPE オーバーレイエフェクトを使用します。


カメラからのレイキャスト ​

一般的なパターンとして、カメラ位置からカメラ方向にレイキャストを行い、プレイヤーが見ているオブジェクトを見つけます。

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

まとめ ​

概念要点
グローバルアクセサーGetCurrentCameraPosition(), GetCurrentCameraDirection(), GetScreenPos()
カメラの種類DayZPlayerCameras 定数(1ST, 3RD_ERC, IRONSIGHTS, OPTICS, VEHICLE など)
現在のタイプplayer.GetCurrentCamera().GetCameraName()
フリーカメラFreeDebugCamera.GetInstance() → cam.SetActive(true)
FOV読み取り: Camera.GetCurrentFOV()、OnUpdate で pOutResult.m_fFovAbsolute を設定
DOFGetGame().OverrideDOF(enable, focusDist, focusLen, focusLenNear, blur, offset)
スクリーン変換GetScreenPos(worldPos) はピクセル XY + 深度 Z を返す

ベストプラクティス ​

  • フレーム内で複数回クエリする場合はカメラ位置をキャッシュしてください。 GetGame().GetCurrentCameraPosition() と GetCurrentCameraDirection() はエンジン呼び出しです --- 同一フレーム内で複数の計算に必要な場合はローカル変数に結果を格納してください。
  • UI 配置前に GetScreenPos() の深度チェックを使用してください。 ワールド位置に HUD マーカーを描画する前に必ず screenPos[2] > 0(カメラの前方)を確認してください。そうしないとマーカーがプレイヤーの背後に反転して表示されます。
  • 単純なエフェクトのためにカスタム ScriptCamera インスタンスを作成することは避けてください。 FreeDebugCamera と PPE システムは、ほとんどのシネマティックおよびビジュアルのニーズをカバーします。カスタムカメラは入力/HUD の管理が複雑で壊れやすくなります。
  • エンジンのカメラタイプ遷移を尊重してください。 プレイヤーコントローラーの状態を完全に処理しない限り、スクリプトからカメラタイプの変更を強制しないでください。予期しないカメラ切り替えはプレイヤーの移動をロックしたりデシンクを引き起こしたりする可能性があります。
  • フリーカメラの使用は管理者/デバッグチェックの背後に置いてください。 FreeDebugCamera は神視点のワールド検査を提供します。悪用を防ぐために、認証された管理者または診断ビルドに対してのみ有効にしてください。

互換性と影響 ​

  • マルチ Mod: カメラアクセサーは読み取り専用のグローバルなので、複数の Mod が安全にカメラ状態を同時に読み取ることができます。衝突が発生するのは、2つの Mod が両方とも FreeDebugCamera またはカスタム ScriptCamera インスタンスをアクティベートしようとした場合のみです。
  • パフォーマンス: GetScreenPos() と GetCurrentCameraPosition() は軽量なエンジン呼び出しです。カメラからのレイキャスト(DayZPhysics.RaycastRV)はより高コストです --- エンティティごとではなく、フレームごとに1回に制限してください。
  • サーバー/クライアント: カメラ状態はクライアントにのみ存在します。すべてのカメラメソッドは専用サーバーでは無意味なデータを返します。サーバーサイドのロジックでカメラクエリを使用しないでください。

<< 前へ: 天候 | カメラ | 次へ: ポストプロセスエフェクト >>

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