ほげたつブログ

プログラムとアニメーションをかじって生きてる

UE4で全体の描画クオリティの調整

UE4ぷちコンもついに最終日ですね。
今回も見ていて面白い作品がたくさんあって楽しいです。

描画クオリティは調整できる

ゲームを作っていると、どうしてもパフォーマンスを上げたいという場面があり、そういった時は描画クオリティを調整する事も視野に入れる必要があります。
ツイート内にも貼ってありますが、UE4ではコンフィグの設定で描画クオリティを調整できるようになっています。

docs.unrealengine.com

また、これらの設定はコンソールコマンドでランタイムで変更ができるので、場面によって切り替えることも可能です。
これはShippingでも有効なので、ゲームのコンフィグ画面を作ってユーザーに調整させるということもできます。

実際にやってみる

テストで動画を撮ってみました。
ちなみにこの動画はエピックさんのサンプルを使用していますが、あえて描画負荷を上げるために可能な限り静的ライトを排除しています。

youtu.be

解像度スケールを下げると全体がボヤけたり、アンチエイリアスを下げるとジャギが発生したり、ポストプロセスを切るとアンビエントオクルージョンが無効化されたり、ランタイムで描画クオリティが変更されているのがわかりますね。
この場面では解像度スケールを下げることで描画負荷を下げることができそうです。
(シャドウを調整する事でも負荷は下がりそうですが、そうするならライトの位置は調整する必要がありそうですね。)

具体的なやり方はコンソールコマンドを実行するだけなので、もしBPからやりたい場合は以下の様になります。

f:id:hogetatu:20151004033951j:plain

基本的には描画クオリティを落とさず、静的ライトへの変更やオブジェクトの削減、ポストプロセスの変更等で対応するのが望ましいかと思いますが、どうしてもという時には有効かと思います。

第4回UE4ぷちコン用のゲームを作りました。「死者を葬る光速の✟反撃(クロスカウンター)」

f:id:hogetatu:20150923010717j:plain

ぷちコンの概要に関しては以下をご覧下さい。

historia.co.jp

今回のテーマは「反射」!

反射というテーマはとても難しく、自分が参加するのもうーんな感じがあるためスルーしようかと思っていたのですが、「ぷち」な感じの軽いネタが思い付いたので、さらっと作ってみました。

youtu.be

ゲームの内容は動画をご覧下さい。
購入アセットを使用しているため、プロジェクトまるまる配布はできないのですが、実行ファイルは追って配布する予定です。

動画にあった裏テーマとは

VRで遊ぶためのゲームデザインを意識してみました!

参考にしたのはCEDEC2015のVRコンテンツ制作のお話。

www.4gamer.net


これを受けて、以下の事に気を付けながら制作しました。

カメラ操作をプレイヤーから奪わない

ゾンビと戦うゲームなので、攻撃されたら地面に転がってマウントポジションから食われてゲームオーバー…みたいな事をやりたいなと初めは思っていましたが、今回はカメラ操作は行わず、UI表示とSE、画面全体を赤くするポストエフェクトで対応しました。

2DのUIを使わない

これは制作開始からずいぶん悩んで試行錯誤しましたが、最終的に狭い空間の壁にUI表示を行うという実装で落ち着きました。
ライトの配置を考慮する事で、目を引きやすく、VR表示にしても情報が自然に入ってくるようにできたかと思います。

フレームレートは75fpsを維持できるように

これは基本ですね。
最終的に僕の環境(GTX970)で75fpsは軽く維持できるように調整しました。

終わりに

久々のVR対応ゲーム制作で楽しかったです。
軽いネタだったため、トータルで2日くらいで作ることが出来ました。(UE4すごい!)
作ったゲームをVR酔いしやすい人に遊んでもらったところ、酔いもなく楽しんでもらえたようで何よりでした。

WebAPIプラグインを使ってオンラインランキング対応とかも考えたのですが、今回は時間の都合でここまでにします。
もし時間ができたら配布するまでに対応するかもしれません。しないかもしれません。

Tobii EyeX が届いたので見つめ合ってみた

f:id:hogetatu:20150907232833j:plain
届きました。

CEDECに行ったら50名限定で無料で貰えるということだったので、せっかくだからと貰ってきました。

Tobii EyeX とは

視線入力デバイスです。
PCの前に座っている人が画面のどこを見ているのかを検知することが出来ます。
これは体験しないとわからないことですが、意外とトラッキングの精度は良いです。
C++用のSDKに加えて、UE4やUnityで使用するためのプラグインも公開されています。

www.tobii.com

さっそく動かす

届いたのですぐさま開封。
開発者登録も済ませ、新参UE4勢なのでUE4のプラグインを見に行ってみたら…

( ゚д゚)…

最新は4.9だというのに…。
とりあえず4.9にコンバートしてみたら案の定ビルドエラーにw

仕方ないのでリポジトリをフォークしてちまちま対応しました。

これで動くと思います。

見つめ合ってみた

ぶっちゃけこれがやりたかっただけです。
UE4マネキンちゃんきゃわわ(棒

まとめ

VRと比べるとできることは少ないかもしれませんが、わざわざデバイスを被ったりしなくていいのは楽でいいですね。
視線トラッキングゲームデザインに組み込むのはなかなか難しいかもしれませんが、もうちょっと何か考えて作ってみたい感じはします。

UE4でBlueprint上からHTTP通信を行うWebApiプラグインを公開しました

2015/10/22 追記 --------

ver.2.0 を公開しました。

hogetatu.hatenablog.com

追記ここまで --------






作りました。


github.com


詳細は日本語READMEを読んで下さい。
https://github.com/HogeTatu/UE4Plugin_WebApi/blob/master/README.jp.md


日本語版の各機能サンプルREADMEを見てもらえれば、なんとなく使い方を想像できるかと思います。


こんな感じで使えます。

https://raw.githubusercontent.com/HogeTatu/UE4Plugin_WebApi/master/Examples/ExampleMovie.gif

利用に関して

【追記】ライセンスに関して一部修正しました

一応これまでの経験を元に商用プロジェクトでも使えるような作りを目指して作っていますが、初めてのプラグイン作成 and 短期間で作ったものなので作りが荒かったりバグがあったりするかもしれません。
ライセンスはMITなので、商用・非商用問わずに好きに使って構いません。


あと英語READMEは拙い英語なので、もし文法的に間違っている点があったら教えてもらえると助かります。。

UE4でレーザービームを実装する


これの実装手順です。
パーティクル作成と発射処理を分けて書こうと思っていた時期もありましたが、パーティクル編がほぼチュートリアルと同じなので割愛することにしました。

パーティクル作成まで

パーティクル用のマテリアルをBeamMaterial、パーティクルをBeamParticleという名前で作成します。
この辺りは上記チュートリアル動画の6:14くらいまでとほぼ同様なので、そちらを見ながら作成して下さい。
チュートリアル動画から、ParticleEmitterに以下の変更を加えています。

  • Lifetimeを0.1に変更
  • InitialColorを(20, 5, 0)に変更
  • SourceのSourceMethodをUserSetに変更
  • TargetのTargetMethodをUserSetに変更

LifetimeやSourceMethod、TargetMethodはBP側からパーティクルの位置や消失を制御するための変更です。

銃のモデルをShooterGameデモから持ってくる

[UE4] 他プロジェクトからアセットを移動させる方法 | historia Inc - 株式会社ヒストリア
この辺りを参考にWeapons/Rifleをコピーしてきます。
ライフルでビーム?とか細かいことは無しで…

腕のメッシュに銃アタッチ用のソケットを追加

hand_rにRightHandという名前でソケットを追加します。
プレビューで見ながら、LocationとRotationをいい感じにします。

f:id:hogetatu:20150728022228j:plain

銃のBPを作成する

FirstPersonGunという名前でBPを作成し、

  • DefaultSceneRoot
    • SkeletalMesh(SkeletalMesh)
      • BeamParticle(ParticleSystem)
        • BeamHitParticle(ParticleSystem)

という階層でコンポーネントを追加します。

SkeletalMesh

  • スケルタルメッシュにRifleを設定

BeamParticle

レーザービーム本体のパーティクルです。

  • ParticlesのTemplateにBeamParticleを設定
  • AutoActivateのチェックを外す

BeamHitParticle

レーザービームが障害物に当たった時の火花パーティクルです。

  • ParticlesのTemplateにP_Sparksを設定
  • AutoActivateのチェックを外す

※P_Sparksは元が青っぽいパーティクルだったので、色をオレンジっぽく変えてあります。

実行時にプレイヤーが銃を持つように設定する

FirstPersonCharacterのBPを開き、イベントグラフに以下の処理を追加します。

f:id:hogetatu:20150728023653j:plain

BeginPlay時に、FirstPersonGunをスポーンし、後から使うためにGunという変数にリファレンスを保持しています。
その後、AttachToを使ってRightHandのソケットに対してアタッチしています。
ここで試しに実行してみて、正常に銃がアタッチされていることを確認します。

レーザービーム発射処理の流れ

  • ビームは照射直後、時間経過により長さが伸びていく
  • ビームの長さには制限がある
  • ビーム停止後はビーム開始点から時間経過により長さが短くなっていく
  • ビームの長さがほぼ0になったら非アクティブ化する

f:id:hogetatu:20150728114943j:plain

必要な変数宣言

FirstPersonGunに必要な変数を宣言します。

  • EmitTimer(float)

ビーム照射時間

  • EmitStopTime(float)

ビーム照射停止時間

  • BeamLenMax(float)

ビームの長さの最大値
動画では5000

  • BeamSpeed(float)

ビームの速さ
動画では10000

  • EmitStartDistance(float)

発射口からのビームパーティクル開始位置

  • EmitEndDistance(float)

発射口からのビームパーティクル終了位置

  • EmitStop(bool)

ビーム照射停止フラグ

照射開始する関数定義

Emit
f:id:hogetatu:20150728131700j:plain

発射口からのビームパーティクル位置設定用の関数定義

値設定時にCLAMPしたかったので、関数として定義します。

SetEmitStartDistance
f:id:hogetatu:20150728132306j:plain

SetEmitEndDistance
f:id:hogetatu:20150728132322j:plain

照射後のビーム更新処理全体図

ここが一番複雑ですが、ひとまず全体の流れです。

f:id:hogetatu:20150728133129j:plain

細かく分割しながら見ていきます。

ビーム有効判定と照射時間更新

f:id:hogetatu:20150728133431j:plain

Emit関数内でBeamParticleをActive化しているので、それを見て更新処理を実行しています。
更新処理の頭では照射開始からの継続時間(照射時間)を更新しています。

ビーム長の更新処理と非アクティブ化判定

f:id:hogetatu:20150728133814j:plain

ビーム照射中は照射停止判定とビームパーティクル終了位置の更新を行います。
ビーム照射停止後はビームパーティクル開始/終了位置どちらも更新が必要です。
また、前述している通り、ビームの長さがほぼ0になる(開始位置が終了位置に追いつく)と非アクティブ化して終了を待ちます。

※パーティクルを非有効化したら放出は止まりますが、すぐには完全に非アクティブになりません。
放出中のものが消えるまで、IsActiveの判定はtrueのままになるので注意が必要です。

ビームパーティクル位置の計算と障害物当たり判定

f:id:hogetatu:20150728134613j:plain

変数上ではビームパーティクルの位置を長さで持っていますが、ここで実際にどの位置なのかの計算を行います。
GetWorldRotationからGetForwardVectorすることでパーティクルの向きが単位ベクトルとして取得できるので、それに長さを掛けたものにGetWorldLocationで取得したパーティクルの原点(発射口)を足してあげることで位置が計算できます。

障害物の当たり判定にはLineTraceByChannelを使用しています。
これはStartとEndの間を直線で辿った時に、ヒットしたものを取得できるものです。
今回の当たり判定では目で見えるものに当たり判定を行いたかったので、TraceChannelはVisibilityで設定してあります。

当たり判定後の処理

f:id:hogetatu:20150728135700j:plain

SetBeamSourcePoint/SetBeamTargetPointはビームパーティクルの開始/終了位置を設定できるものです。
つまりLineTraceした時に、当たり判定開始地点はビームパーティクルの開始地点、実際に当たった地点がビームパーティクルの終了地点という事になります。

当たりが発生した場合、終了位置の更新の他、ビームヒット用パーティクルの有効化、終了位置用の変数を当たった地点に合わせて更新するといった処理を行っています。

当たりが発生しなかった場合は終了位置を当たり判定終了地点に設定するのみです。

Emit関数を呼ぶ

最後にFirstPersonCharacterを開き、照射開始のイベントを追加します。
イベントグラフの中に既にSpawn projectileという処理があり、ここの内容を今回作成したものに置き換えるだけです。

f:id:hogetatu:20150728142016j:plain

これで実装完了です

f:id:hogetatu:20150728141623j:plain

UE4でゲームデータのセーブ/ロード

多くのゲームではデータのセーブ/ロードを実装します。
今回はUE4でローカルファイルへのセーブ/ロードを試してみました。
UE4のバージョンは4.8.2です。

プロジェクト作成

ThirdPersonテンプレートを使用してプロジェクト作成。

キー登録

「編集」→「プロジェクト設定」→「インプット」→「Action Mappings」にキー登録。

  • Load Game
    • 0キー
  • Save Game
    • Shift + 0キー

f:id:hogetatu:20150725234453j:plain

セーブデータクラスを作成

SaveGameを継承してセーブ用のBlueprintを作成します。

f:id:hogetatu:20150725234704j:plain

保存する内容をセーブデータクラスに記述

今回はプレイヤーの位置情報を保存するので、Transform型で「PlayerTransform」という変数を定義します。

f:id:hogetatu:20150725235531j:plain

ロード用の関数定義

レベルのブループリントを開き、LoadGameDataという関数を実装します。

f:id:hogetatu:20150726000203j:plain

GameDataというのはセーブデータクラスをメンバとして宣言したものです。
ロード時はまずGameDataがNullかどうかチェックし、もしNullであれば新規で作成しています。
その後、「Load Game from Slot」でファイル保存されているセーブデータをロードし、プレイヤーの位置情報を上書いています。

セーブデータにはスロット名とユーザーインデックスが指定できます。
スロット名はセーブデータの名前、ユーザーインデックスはその中でのIDみたいなものですね。
ドラクエ冒険の書1とか冒険の書2とかそんなイメージです。

セーブ用の関数定義

レベルのブループリントを開き、SaveGameDataという関数を実装します。

f:id:hogetatu:20150726000758j:plain

セーブ関数が呼ばれたら、プレイヤーの位置情報を取得してGameDataのPlayerTransformを更新し、「Save Game to Slot」でファイル保存しています。

呼び出し処理

レベルのブループリントのイベントグラフを開き、セーブ/ロード用の関数呼び出しを実装します。

f:id:hogetatu:20150726001456j:plain

こんな感じになりました


Windows上でのセーブデータの保存先

[プロジェクト名]/Saved/SaveGames/[スロット名].sav
に保存されているようです。

ちなみにバイナリエディタで開いてみたところ、

f:id:hogetatu:20150726001826j:plain

なので暗号化等はされていないみたいですね。
ローカルに保存するデータなので暗号化は基本的に必要だと思いますが、方法はまた別の機会に調べようと思います。

UE4でカメラズーム

8月からUE4を使う会社で働きます。
なので練習がてらUE4でカメラのズーム機能を実装してみました。
UE4のバージョンは4.8.2です。

【追記】カメラを2つ用意する方法だと近くのオブジェクトが見えなくなる問題があったため、FOVを使う形に記事を修正しました。

プロジェクト作成

FirstPersonテンプレートを使用してプロジェクト作成。

キー登録

「編集」→「プロジェクト設定」→「インプット」→「Action Mappings」にキー登録。

  • CameraZoomToggle
    • 左 Shift

f:id:hogetatu:20150724223536j:plain

ズーム用のカメラコンポーネントを追加

FOVを使用する形に変更するため、工程を削除

FirstPersonCharacterのBlueprintを開き、ズーム時に使用するカメラコンポーネントを追加する。

  • ZoomCamera
    • ロケーションを(1000, 0, 64)に変更
    • Activation の Auto Activate のチェックを外す

f:id:hogetatu:20150724224055j:plain

カメラ切り替え用の処理を記述

イベントグラフを開き、Shift押下時にカメラを切り替えるように記述する。

「CameraZoomToggle」の入力が来た時に「FlipFlop」を使用し、「First Person Camera」と「ZoomCamera」のアクティブ状態を切り替えています。
SetFieldOfViewでカメラの視野角を変更しています。
視野角を小さくすることで描画される範囲が狭くなり、ズーム表示されます。
また、後述するWidgetからの参照用にZoom変数を公開しています。

f:id:hogetatu:20150812001319j:plain

ズーム時に表示するWidgetを設定

ここまででカメラのズーム機能は完了していますが、カメラズーム時にWidgetを表示する事でもっとそれっぽくできます。

FirstPersonWidgetという名前でWidgetを作成し、レベルブループリントに登録します。
この辺りは @aizen76 さんの記事を参考にするといいと思います。

unrealengine.hatenablog.com

デザインは以下の様な感じで、

f:id:hogetatu:20150725002545j:plain

Imageの「Behavior」→「Visibility」をHidden設定にしておき、バインドを以下の処理で登録します。

f:id:hogetatu:20150725002913j:plain

こんな感じになりました