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

お茶漬けびより

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

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

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

概要

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

詳細

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

作成、実装

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

アクターを移動させる Blueprint

UE4
移動系の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 の記事を書いたので間違っているところがあるかもしれません。もし間違いに気付いた方がいらっしゃれば、コメントで指摘していただけると嬉しいです。

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

Tips
個人的によく使うショートカットキーをまとめてみました。
随時更新
 
環境は、ノートパソコンの一画面を想定
以下のショートカットキーを載せています。
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 に参加しました

UE4

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

参加したイベントは以下の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をいじることなく、オブジェクト内をいじるだけで新しいアクションが追加できるようになりました。

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

はてなブログ、始めました

初めに

学んだことを整理するために、はてなブログを始めてみました。

あとで見直して分かりやすい内容になるよう意識して書こうと思います。