メインコンテンツまでスキップ
バージョン: 1.2.0

事前準備

image

概要

事前準備では主に以下の作業を行います。

  • コリジョンチェックの実行に必要な前処理とファイルの準備作業
  • 各 PC にテスト用ファイル一式を配布し、Python 実行環境を構築

対応手順

1. 仮想環境の構築

コリジョンチェック用の Python 仮想環境を構築します。 手順はこちらを参照してください。

2. マップスキャンデータの準備

これ以降の工程は Map Scanner による地形のスキャンが完了した後でなければ行うことはできません。

  1. Python/ フォルダ内に data フォルダ を作成します。

  2. Python/data/ フォルダ内に {ゲーム ID}_{テスト ID} フォルダを作成します。 テスト ID にはゲームのリビジョン番号、ゲームの更新日などを入れてください。 異なるバージョンのゲームでテストを行いたい場合は、ここに新たなフォルダを追加することになります。

  3. マップスキャンで得られたスキャンデータ類を Python/data/{ゲーム ID}_{テスト ID}/ 以下に配置します。これらは {Map Scanner のディレクトリ}/Python/map_data にあります。 最終的に以下のようなファイル構成になっていることを確認してください。 以下に記載されていないファイルが含まれている分には問題ありません。

    Python/

    └ data/
    └ {ゲーム ID}_{テスト ID}/
    └ {マップA}/
    └ road_data/
    └ wall_data/
    └ water_data/
    └ _is_close.npy
    └ _search_map.npy
    └ {マップB}/
    └ …
    └ _map_list.yaml

3. ゲームバイナリの準備

作成済みの Game-Python Bridge が組み込まれたゲームバイナリを、コリジョンチェックフォルダ内にコピーします。 本テストバージョンに対応したゲームバージョンのビルド時に生成された WindowsNoEditor フォルダを Python フォルダ内に配置してください。

4. 座標変換係数の計算とパラメータの追記

コリジョンチェックの結果は専用のビューワーツール (result_viewer.py) を使って行います。 この時、ツール上のマップ画像にテスト結果をプロットするために、ゲーム内の座標とプロット先の座標を対応させる必要があります。 この対応に必要なパラメータ (1 次変換係数) をテスト対象となるマップ毎に計算します。

  1. map_param_calc.py を用いて 1 次変換係数を求めます。使い方はリンク先を参照してください。
  2. Python/data/{ゲーム ID}_{テスト ID}/_map_list.yaml を編集します。
    • Name のフィールドを編集し、マップのゲーム内名称を記載してください。
    • path_params > env_path のフィールドを追加し、3. ゲームバイナリの準備 で配置したゲームバイナリのパスを記載してください。
env_path: ./WindowsNoEditor/Alfort.exe # 変更する内容

map_params:
{ マップID_1 }:
name: { マップ名称_1 } # 変更する内容
drop_threshold: -10 # このマップにおける落下判定しきい値
save_data: None
x:
end: 24
start: -14
y:
end: 10
start: -5
z:
end: 35
start: -5
plot:
coef_x: 0.0 # map_param_calc.py により具体的な数値がセットされているはずです
coef_y: 0.0 # map_param_calc.py により具体的な数値がセットされているはずです
bias_x: 0.0 # map_param_calc.py により具体的な数値がセットされているはずです
bias_y: 0.0 # map_param_calc.py により具体的な数値がセットされているはずです
search_start:
x: 0
y: 0
z: 0
{ マップID_2 }: (略)
備考

_map_list.yaml は Map Scanner と共通の設定ファイルです。
詳しい仕様については こちら を参照してください。

5. セーブデータの作成

コリジョンチェックの実行時やテスト結果の確認時に使用する、選択したマップへ移動するためのセーブデータを作成します。テスト対象としたいマップの数だけ以下の作業を行ってください。

  1. 実際にゲームを操作し、テスト対象としたいマップまでプレイヤーを移動させます。この時、デバッグ移動などを使って移動時間を短縮してもよいですが、必ず移動先のプレイヤー座標が実際のゲームプレーで到達可能な座標になるようにしてください

  2. テスト対象のマップまで移動できたら、ゲームのセーブ機能を使用してセーブデータを作成します。Unreal Engine のビルド済みゲームを用いた場合、ここで作成したセーブデータは WindowsNoEditor/(ゲームのプロジェクト名)/Saved/SaveGames/ 以下に存在する可能性が高いです。

  3. 手順 2 で作成されたセーブデータのファイル名を XXXX.sav とすると、Python/data/{ゲーム ID}_{テスト ID}/{マップ ID}/ 以下にセーブデータをコピーします。

  4. ゲームによっては XXXX.sav に付随して別のファイルが作られる可能性が考えられます。これに該当する場合、そのファイルも手順 3 と同様の手順でコピーしてください。

    備考

    例えば、サンプルゲームではセーブデータ本体である XXXX.sav と同時に SharedData.sav というファイルが作成されます。

6. コリジョンファイルの生成

衝突すべき壁がある箇所を抽出し、その箇所をテスト対象として設定する役割を持つコリジョンファイルを生成します。

  1. Python/make_colfile.py を実行します。このプログラムの実行には 3 つの引数を必ず指定する必要があります。次にある実行例も参照してください。

    • --data: {ゲーム ID}_{テスト ID} フォルダのパス
    • --dist: 目標点の最短配置間隔 (距離単位: なし)
    • --map: コリジョンファイルを生成したいマップの ID
    # 指定したマップのみ実行する場合はマップ ID を指定
    # サンプルゲームの場合は次のいずれか: {PL_010VIL, PL_020RIV, PL_030GRP, PL_050GRH}
    python make_colfile.py --data ./data/alfort_ver1/ --dist 75 --map PL_010VIL
    # 全マップ実行する場合
    python make_colfile.py --data ./data/alfort_ver1/ --dist 75 --map all

    コリジョンファイルの生成が完了するとコンソールに generate finished: {マップ ID} と出力されます。
    生成されるコリジョンファイルは json 形式となっており、以下の構造になっています。

    {
    "Collision": 目標点リスト (dict)
    {
    "{目標点の index}": (dict)
    {
    "X": 目標点座標_X (float),
    "Y": 目標点座標_Y (float),
    "Z": 目標点座標_Z (float),
    "Dir": 衝突方向ベクトル (dict)
    {
    "X": 衝突ベクトルの X 成分 (float),
    "Y": 衝突ベクトルの Y 成分 (float),
    "Z": 衝突ベクトルの Z 成分 (float)
    }
    }
    }
    }
  2. Python/data/{ゲーム ID}_{テスト ID}/{マップ ID}/ 以下にコリジョンファイル collision_completed_{目標点の最短配置間隔}.json があることを確認してください。

備考

make_colfile.py の実行オプション --dist に関して、上記実行例で指定されている値 75 はサンプルゲームにおける最適値です。この値はゲームの地形スケールによって異なると考えられ、値を変えながら何度かコリジョンファイルを生成し、目標点配置が密すぎず疎にもなりすぎない値を探して決めてください。
目標点間隔が密すぎるとテストが入念に行われるメリットがありますが、その分テスト時間が長くなります。 また、スキャンデータのボクセルサイズよりも小さな値に設定しても、アルゴリズム的にそれよりも狭い間隔で配置することはできません。
目標点配置が適切かどうかの確認については、次節の 目標点の配置結果の確認 も参照してください。

7. 目標点の配置結果の確認

coltest_checker.py を使い、目標点が適切な位置に配置できているかどうかを目視確認します。

  1. Python/coltest_checker.py を実行します。すると図のような GUI が表示されます。

    image

  2. 「Select File」ボタンをクリックするとファイル選択ウィンドウが開きます。 「コリジョンファイル」には配置結果を確認したいマップのコリジョンファイル、「マップ情報ファイル」には Python/data/{ゲーム ID}_{テスト ID} に作成した _map_list.yaml を、 「ゲームバイナリ」にはゲーム本体 (exe) のパスをそれぞれ指定してください。

  3. 上記 3 つのファイルを指定した後、「ゲームを起動」をクリックするとゲームが起動します。 どれか一つでも指定されていない場合は起動できません。

  4. ゲームが起動したら、手動で適切な操作を行ってタイトル画面を抜け、ゲーム画面に遷移します。

  5. 手順 2 で指定したコリジョンファイルに対応するマップまで移動します。対象マップがプレイヤーの開始地点から遠い場合、デバッグ移動が便利です。

  6. 対象マップに到着したらキーボードの「@」キーもしくは「^」キーを押します (キーは使用する Unreal Engine のバージョンによって異なります)。
    すると、ゲーム画面左下にコンソールが表示されるので、「coltest_draw_colpoint」と入力し、「Enter」を押します。

  7. 手順 6 の後、コリジョンファイルに記述された目標点がゲームのフィールド内に赤い直方体として描画されます。 フィールド内を歩き回り、通常のプレーでは到達できない箇所に目標点が配置されていないかどうか、逆に配置されるべき箇所なのに配置し損ねていないかどうかを確認してください。

  8. また、目標点の配置結果は GUI 上でも大まかに確認できます。 「▽ 目標点情報」ウィンドウの「表示/非表示」にチェックを入れると、「▽ マップ表示」ウィンドウ内のマップ画像中に目標点が描画されます。赤い丸が目標点、その丸から伸びる黒い線は各目標点に設定された衝突方向 (=衝突すべき壁がある方向) を表しています。この黒い線が壁のある方向に向かって伸びているかどうかも確認してください。 image

  9. 配置結果、及び各目標点に割り振られた衝突方向が適切な場合、コリジョンファイルのファイル名を collision_completed.json に変更します。

    備考

    通常のプレーでは到達できない箇所に目標点が配置されている場合、原因は以下の 2 パターンが考えられます。

    • マップスキャンの不備により、本来は通過不可能な平面 (床、壁、オブジェクトの表面など) となっている部分に穴が空いてしまったため、その内部には入り込むことができるので目標点を配置してもよいとプログラムが判定してしまう
    • 目標点配置アルゴリズムが考慮できていない未知のパターンが存在することで、配置結果が適正なものとならない

    この場合は、その時々に応じた対応が必要となります。

8. テストデータ一式の配置

対応手順「4.座標変換係数の計算とパラメータの追記」〜「7.目標点の配置結果の確認」をテストマップの数だけ繰り返します。

全てのテストマップの準備作業が完了したら、以下のようなファイル構成になっていることを確認してください。

Python/
└ 既存コード色々

└ WindowsNoEditor/
└ data/
└ {ゲーム ID}_{テスト ID}/
└ {マップA}/
└ road_data/
└ wall_data/
└ water_data/
└ _is_close.npy
└ _search_map.npy
└ collision_completed.json - コリジョンファイル
└ XXXX.sav - テスト開始時に読み込むセーブデータ
└ ????.??? - 上記セーブデータに付随するファイル (該当するものが存在する場合)
└ {マップB}/
└ …

9. 他クライアント PC への展開

下記手順により、テストで使用する他の全てのクライアント PC へデータを展開します。

  1. Python フォルダをまるごと zip/7z などに圧縮します。
  2. テストで使用する全 PC に圧縮したファイルを転送します。
  3. テストで使用する全 PC に Python の仮想環境を導入 & 依存パッケージをインストールします。
    1. 上記で転送したファイルを展開します。
    2. 手順 1 で示した Python の仮想環境構築作業を行います。