読者です 読者をやめる 読者になる 読者になる

お茶漬けびより

学んだことを整理する場所です。主に、C++, Unreal Engine 4 (UE4) を扱います。

Microsoft の CI ツールが多くて思考停止したので、整理してみる

【経緯】

唐突にCIツールを使ってみようと思い、Jenkins を自宅サーバ(久々に起動)に入れてみるも、家で作っているのはVisual C++ なので意味ないのでは? と気づき、調べているとMicrosoft のCI ツールを発見。TFS、VSTS、VSO……何がどう違うのか。

【CIとは】

Ceizokuteki Integration のこと……ではなく、Continuous Integration のこと。つまり継続的統合。Cは、コンテニューだと思っておけば覚えやすいかも。まだ利用したことないので理解は浅いけど、変更した内容をすぐに反映、ビルド、テストをすることでバグを早期発見し、品質を高める方法。

で、今回はそのCI環境を作るためのツールを調べたところ、Microsoft の CI ツールが複数あって、混乱したので調べた。

今回紹介するのは、以下

上から時代が古い順に並べたつもり。

簡単に説明すると、初めに Microsoft 製 CI ツールが出たのが、TFS。CI のための基本的な機能(ビルド、テスト、リリースなど)を提供してくれる。ただし、TFS を動かすためのサーバは自分たちで用意する必要がある。

次に VSO 。簡単に言うと Visual Studio のオンライン版。さらに機能が追加され、TFS のような機能も備えている。要は VS + TFS かも。

VSTS。これが今一番新しい。TFS のような機能をクラウドサービスとして提供している。サーバを持つ必要がないので、CI に集中することが出来る。

で、VSTS を動かしているのが Azure。Azure が動かしているので(?)簡単に Azure と連携をすることが出来る。Web 系開発のときに Azure との相性が良い。

気にする必要があるのは、TFS と VSTS。Azure は人による。

TFS より VSTS の方が便利そうだけど、TFS はローカルで構築することが出来るので、全く利用価値がないわけではない。

全体としては以上。一つ一つ紹介していく

Team Foundation Server(TFS)】

大きな機能として、バージョン管理、アジャイル開発をするときに便利なツールやビルド、パッケージ、テスト、リリースを自動で行うなどの機能を備えている。

ローカルで解決したいときは、こいつをインストールする。

Visual Studio Online(VSO)】

特に重要ではないので簡単に説明する。

VS + TFS のオンライン版。つまりクラウドサービス。現在は、Visual Studio Team Services(あとで紹介)という名前に変わっている。なので、説明は VSTS に譲る。

Visual Studio Team Services】

一番名前が長い。CIのための基本的な機能はもちろん。サーバの構築が不要で、サインアップするだけで利用することが出来る。

このサービスは、Azure の上で動いているので、Azure のサービスの一つだと思って良さそう。個人で使うだけなら無料で利用可能(利用人数によるが)。Azure との相性が良いので、Azure を使った、Web アプリを開発したり、Xamarin を使ったスマフォアプリ開発などに便利(どちらも作ったことないので見当違いなこと書いてるかも……)。

CI 機能使わないから関係ないと思っている人にも知っていて欲しいのが(ここまで読んでいるか怪しいけど)、バージョン管理。

例えば、バージョン管理のためのサーバが欲しい。けど、Github は無料だと公開しないといけない恥ずかしいって人は、VSTS を使うと良いかもしれない(あまりそういう籠もる姿勢はおすすめしないけど)。なんとバージョン管理をプライベートで利用できる。バージョン管理のツールは Git に近い感じ。Git も使うことが出来る。

Visual Studio 2017 では、VSTS を利用するための機能が強化されるそうなので、VSTS を検討する余地はあるかと。 

【参考資料】

Team Foundation Server - Visual Studio

www.visualstudio.com

blogs.msdn.microsoft.com

Visual Studio Team Services - Visual Studio

  • Azure

docs.microsoft.com

www.atmarkit.co.jp

C++ のエラー処理

本に書いてあったエラー処理の話がためになりそうだったので、ここにまとめておこうかと思います。

参考にした本は、以下の2冊です。

C++のためのAPIデザイン

C++のためのAPIデザイン

 

4.7.4 「エラーの処理方法」を参考にしました。

ゲームエンジン・アーキテクチャ 第2版

ゲームエンジン・アーキテクチャ 第2版

 

 ゲームエンジンアーキテクチャは、3.3 「エラーの補足と処理」を参考にしました。

また、自分が持っている本は第1版です。 

 

では、まとめていきます。

 

まず、C++のためのAPIデザインの内容です。

エラーが発生した場合に対処する方法は、主に3つです。

  • エラーコードを返す
  • 例外を投げる
  • プログラムを停止する

では、一つずつ見ていきます。

エラーコードを返す

これは、エラー内容を値に置き換えることで対処する方法です。単純でありながら非常に便利です。今回はC++なのでエラーの対処法の一つになりますが、純粋なCの場合だと唯一の方法になります。

また、関数自体が何か値を返したいときにどちらか片方しか返せません。この場合は、エラーコードを返し、引数に値を入れることで対処します。

boost::tuple を使うと複数の結果を返すことが出来るようです。

例外を投げる

これはC++の例外処理を使います。関数が投げてきたオブジェクトを受け取り、対処します。例外を使うとエラー処理と通常の処理を別に切り分けることが出来るので、コードが読みやすくなります。また、シンプルなエラーコードよりも多くの情報を持たせることができます。さらに、大抵のデバッガは例外が発生するとそこで処理が止まってくれる(ブレーク)ので、デバッグが行いやすくなります。しかし、想定外の例外が発生するとプログラムが停止する恐れがあります。また通常は一部でも例外を使用する場合、そのアプリ全体で例外処理を正しく行うようにする必要があります。

エラーが発生した場合は、すぐに関数の処理を停止し、直前に割り当てられていたリソースを解放することが最善です。ただし、NULLなどの例外の値は返さないようにしましょう。関数を呼び出した側がさらにその例外の値をチェックする必要があるからです。この場合は、空のリストを返すようにするといいかもしれません。

エラー時に情報はなるべく多く、エラーの原因を早く突き止められるような情報を載せましょう。

 

次にゲームエンジンアーキテクチャの内容です。

エラーには、大きく分けて二つあります。ユーザエラーとプログラマエラーです。

ユーザエラーは、ソフトウェアを使うユーザが引き起こすエラーで、プログラマエラーはコード自体のバグです。ただし、ユーザにはさらに2種類に分けることができます。

一つは、ゲームをプレイしているユーザで、もう一つは、ゲームを制作しているユーザが引き起こすエラーです。

まとめると

ユーザエラー
  • プレイヤーエラー(ソフトウェア使用者)
  • 開発者エラー

プログラマエラー

大きく分けて2つ。細かく分けて3つのエラーの種類があります。

このユーザエラーとプログラマエラー、2つのタイプによってエラーの対処法は変わります。

ユーザエラーの場合、ゲームをプレイしていたりゲーム制作の作業をしているのでゲームや作業を止めるようなことはあってはいけません。処理を継続しながらも、ユーザの役に立つ情報を提供することが大事です。

逆にプログラマエラーの場合は、処理を止める必要があります。そして、デバッグを行うために必要な情報を提供します。

では、さらに細かく見ていきます。

プレイヤーエラー

ゲームをプレイしているときのエラーです。当然ゲームが止まるようなことはあってはいけません。そのような重度なエラーでなくとも、例えば、アイテムが0のときにアイテムを使用すると、そのアイテムは使用されずにプレイヤーに今は使うことが出来ないということを知らせる。これもプレイヤーエラーになるでしょう。

開発者エラー

これは、アーティストやアニメーターなどに起こるエラーです。例えばアセット(や画像)のようなデータを読みこませるときに、そのアセット自身が原因で起こるエラーです。このような問題のあるデータをエラーに気づかずまたは無視されていると、そのデータが入ったまま製品として出されることになります。かといって、問題があるから停止をさせると開発者の手が止まり、作業が進まなくなってしまいます。

なのでこの場合は、エラーであることを開発者に分かりやすく伝えながらも処理を継続させます。

プログラマーエラー

プログラマーエラーの場合は、本来あってはならないのですぐに処理を止めます。こうすることで、プログラマーは嫌でもバグを取り除くことになります。

 

では、エラーの検出、実装方法は何があるのでしょうか。

これはC++のためのAPIデザインにもあったエラーコードと例外。そして、アサートです。アサートは、式をチェックする命令行のことで、これを正しく使用することでプログラマはこれに引っかかると、引っかかった原因を取り除く必要があります。なので、上記の3つのエラーの中では、プログラマーエラーに使われるでしょう。またアサートは通常マクロで定義されるので、製品として出すときは取り除くことが出来ます。

以上、雑なまとめになりますが終わります。

今回のことで分かったのは、エラーの種類には複数あり、その種類によって対処の仕方は全然変わってくるということです。プログラマーのエラーには主にアサートを使い、開発者エラーの場合は、例外処理で処理を継続しつつエラーの情報を提供し、プレイヤーエラーのときは、エラーコードを使用して対処するという感じでしょうか。

そうすると統一性がなくぐちゃぐちゃになりそうですが……。アサートの使い道は分かりやすいですが、エラーコードと例外をどう使い分ければいいかがまだ分かりませんので、エラー処理の対処は、とにかく試行錯誤していくしかなさそうです……。

 

 

UE4 の Blueprint インタフェースについて

Blueprint(以下BP)のインタフェース(インターフェース)について調べました。

概要

BP のインタフェースは、見た目はBPクラスですが中身は少し違います。インタフェースには出来ることと、出来ないことがあります。
出来ること
  • 関数の作成
  • 関数の入出力の追加
  • 純粋(const)化*1
出来ないこと

詳細

インタフェースでは、関数の外枠だけを作り、中身は作りません。その中身は、インタフェースを実装したBPクラスに任せてしまいます。外枠を決めることで、このインタフェースを実装したBPクラスたちは、共通の関数を持つことが出来ます。つまり、同じインタフェースを実装したクラスたちの共通の関数を呼び出すだけで、それぞれ異なる動作を行わせることが出来ます。
インタフェースでは関数の外枠を作るわけですが、その外枠とは、具体的には関数の名前や入力、出力する値、純粋化するかどうかを決めます。逆にこれらは、インタフェースを実装したBPクラス側では編集できません。外枠を変えることが出来ると共通の関数を持つことにならないからです。
説明としては以上です。インタフェース自体は効率化を進めるための機能だと思うので、知らなくてもゲームは作れます。なので、あまりUE4に慣れていない間はあまり気にする必要はないでしょう。
 
作成した関数は、BPクラス側のインターフェースに表示される関数と表示されない関数があります。この違いは何でしょうか?
いろいろ試して分かったことは、BPクラスのインターフェースに表示される関数は、
  • 出力される値(アウトプット)がある
  • 純粋関数である(Const にチェックをしている)
この二つの内一つでも当てはまるものは、BPクラス側のインターフェースとして表示されます。
表示されない関数たちはどこにいったかというと、イベントグラフ上でノード検索を行い(右クリック)、関数の名前を入力すると「イベント○○(関数名)」と表示されます。これをクリックすることでインタフェースの関数をイベントとして追加できます。あとはBPクラス側で実装をすることで関数の中身を作ることができます。

作成、実装

実際の作成や実装の手順は、公式が書いてくれているのでそちらに任せます。
 
 
 

アクターを移動させる Blueprint

移動系のBleuprint(BP)を調べたのでまとめます。
といっても基本的な内容なので、大したものではないのですが。
 
アクターを移動させるためのBPはいろいろあると思います。
今回は、以下を調べました。
  • SetActorLocation
  • SetActorRelativeLocation
  • AddActorWorldOffset
  • AddActorLocalOffset
ここでは、SetActorLocation と SetActorRelativeLocation のことをまとめて、Location 系と呼び、AddActorWorldOffset と AddActorLocalOffset のことをまとめて、Offset 系と呼ぶことにします。 

Location 系

・SetActorLocation 

Input
Target(Actor Reference)
移動させたいアクター(以下ターゲット)を指定
New Location(Vector
世界座標の位置を指定。
Sweep(Boolean)
True のとき有効。ターゲットが物体にぶつかるとターゲットは停止する。
Teleport(Boolean)

指定した位置に瞬間移動するようになる

 
Output
Sweep Hit Result(Hit Result Structure)
Sweep を有効にしているときに何かにぶつかると Hit Result Structureとして返す
Return Value
移動に成功したとき True を返す。Sweep が無効のときは必ず True になる(はず)

詳細
New Location で指定した世界座標(ワールド座標、絶対座標)の位置に物体を動かします。Sweep を有効にすると現在位置から New Location の直線状に物体があるとその物体の手前で止まります。
Sweep についてはいくつか注意する点があります。
  • Sweep の機能は、ターゲットとぶつかる対象の両方が、Collison のオブジェクト応答でブロックしているとき機能する。
  • ターゲットは、ルートコンポーネントコリジョンの設定(オブジェクト応答)をしないと機能しない。
  • 注意ではないが、「オーバーラップイベントを発行させる」は有効にしなくてよい。
2つ目のルートコンポーネントコリジョンの設定をする話は、Sweep の仕様というよりもコリジョンの問題っぽい?*1
Teleport は、ルートコンポーネントについている別のコンポーネント側に移動速度を反映させないようにするようです*2

・SetActorRelativeLocation

Input
Target(Actor Reference)
移動させたいアクター(以下ターゲット)を指定
New Relative Location(Vector
アウトライナ上で親子関係のある、親を中心(0, 0, 0)とした座標位置を指定。
Sweep(Boolean)
True のとき有効。ターゲットが物体にぶつかるとターゲットは停止する。
 
Output
Sweep Hit Result(Hit Result Structure)
Sweep を有効にしているときに何かにぶつかると Hit Result Structure として返す
詳細
機能としてはほとんど同じですが、移動するときの基準となる座標が違います。
SetActorLocation のときは世界座標でしたが、SetActorRelativeLocation の場合は、親の位置を中心(0, 0, 0)とした相対座標(ローカル座標)になります。ここでいう親というのは、アウトライナ上の親子関係のことです。親子関係は、アクタを別のアクタにドラッグすること(アタッチ)で作れます。この場合、ドラッグ側のアクタがドラッグ先のアクタの子になります*3

Offset 系 

・AddActorWorldOffset

Input
Target(Actor Reference)
移動させたいアクター(以下ターゲット)を指定
Delta Location(Vector
ターゲットの現在位置から Delta Location だけ世界座標を軸に移動する。
Sweep(Boolean)
True のとき有効。ターゲットが物体にぶつかるとターゲットは停止する。
Teleport(Boolean)
指定した位置に瞬間移動するようになる。

Output
Sweep Hit Result(Hit Result Structure)
Sweep を有効にしているときに何かにぶつかると Hit Result Structure として返す


・AddActorLocalOffset

Input
Target(Actor Reference)
移動させたいアクター(以下ターゲット)を指定
Delta Location(Vector
ターゲットの現在位置から Delta Location だけ相対座標を軸に移動する。
Sweep(Boolean)
True のとき有効。ターゲットが物体にぶつかるとターゲットは停止する。
Teleport(Boolean)
指定した位置に瞬間移動するようになる。

Output
Sweep Hit Result(Hit Result Structure)
Sweep を有効にしているときに何かにぶつかるとHit Result Structure として返す
詳細
二つをまとめて紹介したほうが、分かりやすいと思ったので同時に説明します。
まずこの二つの名前には Offset というのが付いていますが、Offset とは何でしょうか?
上記の内容が分かりやすかったので、載せておきます。これによると Offset は基準の位置からのズレということです。つまり Offset 系は、ターゲットの位置を基準とした位置から Delta Location の分だけズラすということでしょう。ということは、これを使えばわざわざ Location 系を使うときに、(現在位置+移動量)の値を New Location にする必要はなさそうです。 
では、 Local と World の違いは何でしょうか。これは憶測ですが基準となる軸のことを指していると思っています。つまり、Local の場合はローカル座標(相対座標)を軸とした移動で、World は世界座標を軸とした移動になるということです。
例えば、以下の図のようなローカル座標があるとします。

f:id:pickles-ochazuke:20170104032751j:plain

このローカル座標は、ターゲット自身の座標です。この状態で AddActorLocalOffset の Delta Location に(0, 10, 0)の Vector を設定すると、Y軸方向に 10 進みます。これは下図のように前方に進んでいるように見えます。

f:id:pickles-ochazuke:20170104032849j:plain

では、この Local 座標の Z 軸を 90 度回転します。すると下図のようになりました。

f:id:pickles-ochazuke:20170104032917j:plain

この状態で先ほどと同じように移動させてみましょう。Y 軸方向に 10 進みます。これは、下図のようになります。

f:id:pickles-ochazuke:20170104032938j:plain

つまり、 AddActorLocalOffset はターゲットが回転すると、その影響を受けて移動をするということです。
逆に AddActorWorldOffset はターゲットが回転をしても影響ありません。ローカル座標ではなく世界座標を軸に移動しているからです。もちろん世界座標が回転をすれば、AddActorWorldOffset は影響を受けます。この場合 AddActorLocalOffset は影響を受けないはずです(憶測です……)。
また、ターゲットが親子関係を持っている場合、AddActorLocalOffset はターゲット自身の軸と親の軸、両方の軸を見ている(合わせている?)ようです。ややこしいのですが、例えば親が Z 軸右に 90 度回転していて、ターゲット自身も Z 軸右に 90 度回転している場合、二つの回転を合わせた Z 軸 180 度回転した軸を基準に移動するようになります。
 
以上、Offset 系の説明でした。長々と説明しましたが、説明を読むよりも実際にBPを組んでみたほうが実感が湧くと思います。自分もこの記事を書きながら実行をするなかでいくつか疑問点が出て、実際に試して疑問を解消したので手で動かすことをオススメします(ただ手を動かすのではなく、考えて動かすこと)。
 
最後に、とても参考になった記事
以上です。初めての BP の記事を書いたので間違っているところがあるかもしれません。もし間違いに気付いた方がいらっしゃれば、コメントで指摘していただけると嬉しいです。

プログラミングするときに使うショートカットキー集

個人的によく使うショートカットキーをまとめてみました。
随時更新
 
環境は、ノートパソコンの一画面を想定
以下のショートカットキーを載せています。
Widnows10
ノートで開発するとき画面が一画面かつ小さいので作業がしづらいです。
なので、Windows10から追加された仮想デスクトップを使っています。
 
仮想デスクトップ間の移動
Windowsキー + Ctrl + (← or →)
アプリケーションの切り替え
Alt + Tab
 
 
 
 
 
 
 
 
 
Visual Studio 2017 RC
Visual Stduio のショートカットキーは、最近調べ始めたのでところどころマウス使っています。
&& は、「その後に続けて」という意味で使っています
 
タブ切り替え
Ctrl + Tab
Ctrl + K && Ctrl + C
Ctrl + K && Ctrl + U
矩形選択
Shift + Alt
文字検索
Ctrl + F
文字置換
Ctrl + H
入力補間
Ctrl + Space
ビルド
Ctrl + Shift + B
デバッグなしで開始
Ctrl + F5
デバッグの開始
F5
 
 
 
Google Search
あまりショートカット気にしなかったのですが、使ってみると便利でした。
 
 検索バーに移動
/(全角でも可。ただし検索バーに「・」が表示される)
検索結果に移動
Tab
検索結果の移動
(↑キー, ↓キー) or ( j, k )
 
 
 
Microsoft Edge
最近使い始めました。とくに不満なく使えています。
 
タブを開く
Ctrl + T
タブを閉じる
Ctrl + W
戻る
Ctrl + ← or Backspace
進む
Ctrl + →
アドレスバーに移動
Ctrl + L



第2回 関西UE4 GameJam に参加しました

初めてゲームジャムに参加してきましたので、その反省をしたいと思います。

参加したイベントは以下のURLです。

connpass.com

あまりゲームジャムのことは書いていませんが、参加しようと迷っている方は最後の方だけでも読んでいくと良いかもしれません。

 

自分は主にプログラム(ブループリント(以下、BP))担当でした。

他にプログラムを作る人は二人いて、一人はUE4で仕事をしているようなプロの方でした(とてもお世話になり、助かりました)。もう一人は学生でした(同じくお世話になりました)。

自分のチームが作ったゲームは、競争型の4人対戦ゲームです。

簡単に言うとアイスクライマーのようなゲームなのですが、足場が小さくジャンプで足場から足場に飛び移って上を目指すゲームです。

このゲーム開発の中で自分は、床の制作を担当しました。床といってもただの床ではなく、下からジャンプでぶつかると壊れたり、床の角度が変わったり、通常は下から床を抜けることは出来ませんが、それが可能な床であったりといくつかギミックを作りました。そのうちいくつかは時間が足らず実装に間に合わないものもありました。

それ以外にも拾って使うことで有利になるアイテムを作成しました。といってもアイテムの型は他の方が作成し、機能の部分のみを作るという感じでしたが(自分にもっと力があれば……!)。

作成したモノの紹介はまた別の機会にするとして、今回は反省でこうすればよかった。ここが自分には足りていないなとか、こうしてよかったこと(あれば)などを書いていこうと思います。

 メモを取る

時間は限られており、自分がする作業を忘れたり情報に齟齬が生まれるということは避けたいです。メモは取っていましたが、メモしきれておらず何度か作業を確認したり、勘違いしていることがあったりと時間を無駄にしてしまいました。

メモは紙に書いていたので、PCを使っていればメモしきれていないという状況は避けられたかもしれません。

また、自分はあまり聞き取り上手ではないので、話が早いとついていけないことがあります(ここら辺ってどうやったらついていけるようになるんだろう……)。途中で何の話をしているのか分からなくなったり、話の結果どうなったのか分からなかった場合は、すぐにその場でリーダーに聞くというのが最善かなと思いました。

ゲームのことで甘く見ていたのか、思っているよりも自分の知らない単語が出てきたので、プログラム周りだけでなくゲーム全体の作業を知っておくともう少しついていけたのかも……?

まとめると上記は、主にコミュニケーション能力になるでしょうか。

・メモは一番情報を得ることが出来る方法で取る。

・会話に参加できるように分からなくなったらその場で聞く。

こう書くととても当たり前のことですね。

これを少しでも克服するためには、人と話す機会を増やしたり要点をまとめる癖(勉強したことをまとめたり、ブログを書いたり)をつけるといいのかもしれません。

基本的な手段や基礎は、調べなくても出来るようになる

これは主にBPのことです。

BPの簡単なことはできるようになったと自負していたのですが、思っていたより上手くいかず、そのたびに調べたり人に聞いたりしていました。今回の件でBPでよく使う機能や手順は調べなくても手癖で出来るようになろうと思いました。

BPの簡単なことというのは、オブジェクトの移動や回転のノードの機能(相対的な移動や絶対的な移動)を把握しておくことや、フロー制御の機能、一定間隔で動いたり何かイベントを起こすといった方法などです。

また、ノードだけに詳しくなるのではなく、BPの機能的な部分も詳しくなりたいので、BPの継承であったり、インタフェース、ディスパッチャーや関数、上記に書いたフロー制御といったBPの基礎?を勉強したほうが良いと感じました。ここら辺を知っておくと速く良いものが作れそうです。

改めて考えてみると、ノードのことはよく調べるのですがBPの基礎?はあまり調べたことがありませんでした。プログラム言語だと基礎となる関数の作り方や制御フロー、インタフェースといったことを調べて開発を進めていくのですが、BPはそれを知らなくてもノードの機能を利用することで作れてしまうことが多い気がします(まだ経験が浅いですが)。調べてみてもUE4の入門は、BPを使ってゲームの開発を出来るようにすることに焦点を当てているので、機能部分はあまり見ません(というか必要ない)。これは良いことではあるのですが。

プログラマーとしてBPの基礎は知っておくべきだと感じたので、これを機に調べてみようと思います。

まとめると上記は、BPの基礎能力でしょうか。

  • BPの基礎(フロー制御、継承、インタフェース、関数、ディスパッチャー)を理解する。
  • BPの基本的なノードの機能(回転、移動、拡縮、Timelineや様々なイベント)を把握しておく。

 

以上が今回のゲームジャムで得た自分の課題です。

初めはゲームジャムのことを書こうと思ったのですが、特に説明することがないなと思いやめました(本当にURL先のスケジュールのような感じでした)。

ゲームジャムがどんなところか知りたいという人は、とりあえずゲームを作りたいという気持ちを持ってゲームジャムに参加するのが一番だと思います。特にUnityやUE4のようなゲームエンジンを使うゲームジャムはかなり参加しやすいです。

自分は3Dのゲーム開発はしたことがなく、UE4で簡単な機能を作れる程度の能力ですが、それでも参加をしていくつか機能を作ることが出来ましたから。

ゲームを作る能力がない、でもゲームを作りたいという気持ちがある(これが一番重要です)人は、Unity、UE4などのゲームエンジンを使うゲームジャムに参加するときっと良い経験になると思います。もちろんゲームエンジンを限定していないゲームジャムでも良いです。

特に学生の方は今すぐにでもゲームジャムに参加するべきです。社会人だと今よりも参加しづらくなります。基本土日に開催されると思うので、社会人になるとゲームジャムで丸二日作業して次の日仕事……ってなるので。自分はそれでも人とゲーム開発をしてみたかったので参加しましたが。

学生なら月曜の授業や土日月?のバイトをサボっても良いんです。授業より、数時間のバイトで得た金額よりも必ず得られるものがあります。というのも授業や数千のバイト代はあとで取り返せます。ゲームジャムはその時しかありません。

と、最後に学生の方に向けて書いてみましたが、これは学生のときに何で自分は参加しなかったのだろうと後悔しているからです。一人でゲーム開発をしている方はぜひ参加してみてください。きっと良い日になります。

操作キャラクターの目の前にあるオブジェクトのイベントを呼ぶ

初記事です。UE4の話です。

 今回作った機能は、アクションボタンを押したときにオブジェクトによって異なるアクションを起こす機能です。例えば、ゼルダの伝説というゲームがありますが、Aボタンを押すだけでも状況によってアクションが変化します。宝箱が近くにあれば宝箱を開け、登れる壁があれば登り、押せるオブジェクトがあれば押したりなど。そんな機能を作ります。

 手順としては、アクション用のBPクラスを作り、イベントディスパッチャーを使って、プレイヤーからオブジェクトのイベントを起こします。

まず簡単に流れを考えます。

アクションボタンを押す

目の前にオブジェクトがある?―(ない)→終了

↓ある

アクションイベントを持っている?ー(ない)→終了

↓ある

アクションイベントを呼び出す

終了

この流れを、操作キャラクターのBPに追加します。

 

アクションボタンを押す

これは、プロジェクトの設定からインプットにあるAction Mappingsで追加します。

今回、名前は「Action」にしました。

 

目の前にオブジェクトがある?

これは、LineTraceByChannel を使います。

LineTraceByChannelについては、以下を参照ください。

docs.unrealengine.com

以下のように組みました。

f:id:pickles-ochazuke:20161123100311p:plain

 

アクションイベントを持っている?

今回の本題です。

まず、アクターにアクションイベントを持たせます。そのために新しいコンポーネント(アクションコンポーネント)を作成し、そのコンポーネントにイベントディスパッチャー(アクションイベント)を作ります。そして、アクション用のアクター(アクションアクター)を作り、アクションコンポーネントを追加し、アクションを持っていることが分かるようにタグを追加します。アクションイベントを持たせたいアクターを作るときは、このアクションアクターを継承するようにします。

図にすると以下のような感じです。

f:id:pickles-ochazuke:20161123111027j:plain

では、まずコンポーネントを作っていきます。

コンテンツブラウザの新規作成からブループリントクラスを選び、親クラスとしてActorComponentを選びます。作ったコンポーネントの名前は、ActionComponentとしました。

f:id:pickles-ochazuke:20161123111506p:plain

次にBPを開いて、イベントディスパッチャーを追加します。

名前はActionDispatchにしました。

f:id:pickles-ochazuke:20161123112055p:plain

次にアクション用のアクターを作ります。

コンテンツブラウザから新規作成でブループリントクラスを選びます。親クラスはActorを選びます。作成したBPの名前は、ActionActorBPにしました。ActionActorBPを開いて、コンポーネントを追加からActionComponentを追加します。クラスのデフォルトを選んだ状態で、詳細のActorのTagsのタグを追加します。タグの名前は、Actionにしました。

f:id:pickles-ochazuke:20161123113211p:plain

これでアクション用のアクターは完成です。あとはアクションを付けるアクターを作るときにActionActorBPを親クラスに選び、ActionComponentのActionDispatchをイベントに追加すれば、OKです。

では、操作キャラクターのBPに戻ります。

まず、ヒットしたActorがActionタグを持っているか見ます。Actionタグがあるということは、アクションイベントを持っていると判断し、ActionDispatchを呼び出します。これで、ヒットしたActorのアクションイベントを呼びます。

BPは以下のようになります。

f:id:pickles-ochazuke:20161123114238p:plain

 

アクションイベントを呼び出す

一応流れとしては完成していますが、試しにイベントを呼び出してみます。

ActionActorBPを親クラスに選び、ActionChild1とActionChild2を作ります。

そして、ActionDispatchをイベントに追加し、分かりやすいようにPrint String でてきとうな文字を入力します。もちろんActionChild1とActionChild2は別々の文字を出力するようにします。

細かい説明は面倒なので、以下の動画をご覧ください。

youtu.be

これで、操作キャラクター側のBPをいじることなく、オブジェクト内をいじるだけで新しいアクションが追加できるようになりました。

もっと簡単な方法や、何か問題があるかもしれませんが、分かり次第追記しようと思います。