C++ のエラー処理
本に書いてあったエラー処理の話がためになりそうだったので、ここにまとめておこうかと思います。
参考にした本は、以下の2冊です。
4.7.4 「エラーの処理方法」を参考にしました。
ゲームエンジン・アーキテクチャは、3.3 「エラーの補足と処理」を参考にしました。
また、自分が持っている本は第1版です。
では、まとめていきます。
エラーが発生した場合に対処する方法は、主に3つです。
- エラーコードを返す
- 例外を投げる
- プログラムを停止する
では、一つずつ見ていきます。
エラーコードを返す
これは、エラー内容を値に置き換えることで対処する方法です。単純でありながら非常に便利です。今回はC++なのでエラーの対処法の一つになりますが、純粋なCの場合だと唯一の方法になります。
また、関数自体が何か値を返したいときにどちらか片方しか返せません。この場合は、エラーコードを返し、引数に値を入れることで対処します。
boost::tuple を使うと複数の結果を返すことが出来るようです。
例外を投げる
これはC++の例外処理を使います。関数が投げてきたオブジェクトを受け取り、対処します。例外を使うとエラー処理と通常の処理を別に切り分けることが出来るので、コードが読みやすくなります。また、シンプルなエラーコードよりも多くの情報を持たせることができます。さらに、大抵のデバッガは例外が発生するとそこで処理が止まってくれる(ブレーク)ので、デバッグが行いやすくなります。しかし、想定外の例外が発生するとプログラムが停止する恐れがあります。また通常は一部でも例外を使用する場合、そのアプリ全体で例外処理を正しく行うようにする必要があります。
エラーが発生した場合は、すぐに関数の処理を停止し、直前に割り当てられていたリソースを解放することが最善です。ただし、NULLなどの例外の値は返さないようにしましょう。関数を呼び出した側がさらにその例外の値をチェックする必要があるからです。この場合は、空のリストを返すようにするといいかもしれません。
エラー時に情報はなるべく多く、エラーの原因を早く突き止められるような情報を載せましょう。
エラーには、大きく分けて二つあります。ユーザエラーとプログラマエラーです。
ユーザエラーは、ソフトウェアを使うユーザが引き起こすエラーで、プログラマエラーはコード自体のバグです。ただし、ユーザにはさらに2種類に分けることができます。
一つは、ゲームをプレイしているユーザで、もう一つは、ゲームを制作しているユーザが引き起こすエラーです。
まとめると
ユーザエラー
- プレイヤーエラー(ソフトウェア使用者)
-
開発者エラー
プログラマエラー
大きく分けて2つ。細かく分けて3つのエラーの種類があります。
このユーザエラーとプログラマエラー、2つのタイプによってエラーの対処法は変わります。
ユーザエラーの場合、ゲームをプレイしていたりゲーム制作の作業をしているのでゲームや作業を止めるようなことはあってはいけません。処理を継続しながらも、ユーザの役に立つ情報を提供することが大事です。
逆にプログラマエラーの場合は、処理を止める必要があります。そして、デバッグを行うために必要な情報を提供します。
では、さらに細かく見ていきます。
プレイヤーエラー
ゲームをプレイしているときのエラーです。当然ゲームが止まるようなことはあってはいけません。そのような重度なエラーでなくとも、例えば、アイテムが0のときにアイテムを使用すると、そのアイテムは使用されずにプレイヤーに今は使うことが出来ないということを知らせる。これもプレイヤーエラーになるでしょう。
開発者エラー
これは、アーティストやアニメーターなどに起こるエラーです。例えばアセット(や画像)のようなデータを読みこませるときに、そのアセット自身が原因で起こるエラーです。このような問題のあるデータをエラーに気づかずまたは無視されていると、そのデータが入ったまま製品として出されることになります。かといって、問題があるから停止をさせると開発者の手が止まり、作業が進まなくなってしまいます。
なのでこの場合は、エラーであることを開発者に分かりやすく伝えながらも処理を継続させます。
プログラマーエラー
プログラマーエラーの場合は、本来あってはならないのですぐに処理を止めます。こうすることで、プログラマーは嫌でもバグを取り除くことになります。
では、エラーの検出、実装方法は何があるのでしょうか。
これはC++のためのAPIデザインにもあったエラーコードと例外。そして、アサートです。アサートは、式をチェックする命令行のことで、これを正しく使用することでプログラマはこれに引っかかると、引っかかった原因を取り除く必要があります。なので、上記の3つのエラーの中では、プログラマーエラーに使われるでしょう。またアサートは通常マクロで定義されるので、製品として出すときは取り除くことが出来ます。
以上、雑なまとめになりますが終わります。
今回のことで分かったのは、エラーの種類には複数あり、その種類によって対処の仕方は全然変わってくるということです。プログラマーのエラーには主にアサートを使い、開発者エラーの場合は、例外処理で処理を継続しつつエラーの情報を提供し、プレイヤーエラーのときは、エラーコードを使用して対処するという感じでしょうか。
そうすると統一性がなくぐちゃぐちゃになりそうですが……。アサートの使い道は分かりやすいですが、エラーコードと例外をどう使い分ければいいかがまだ分かりませんので、エラー処理の対処は、とにかく試行錯誤していくしかなさそうです……。
UE4 の Blueprint インタフェースについて
概要
出来ること
- 関数の作成
- 関数の入出力の追加
- 純粋(const)化*1
出来ないこと
- 変数の追加
- グラフの編集
- コンポーネントの追加
詳細
- 出力される値(アウトプット)がある
- 純粋関数である(Const にチェックをしている)
作成、実装
アクターを移動させる Blueprint
- SetActorLocation
- SetActorRelativeLocation
- AddActorWorldOffset
- AddActorLocalOffset
Location 系
・SetActorLocation
Target(Actor Reference)
|
移動させたいアクター(以下ターゲット)を指定
|
New Location(Vector)
|
世界座標の位置を指定。
|
Sweep(Boolean)
|
True のとき有効。ターゲットが物体にぶつかるとターゲットは停止する。
|
Teleport(Boolean)
|
指定した位置に瞬間移動するようになる |
Sweep Hit Result(Hit Result Structure)
|
Sweep を有効にしているときに何かにぶつかると Hit Result Structureとして返す
|
Return Value
|
移動に成功したとき True を返す。Sweep が無効のときは必ず True になる(はず)
|
詳細
- Sweep の機能は、ターゲットとぶつかる対象の両方が、Collison のオブジェクト応答でブロックしているとき機能する。
- ターゲットは、ルートコンポーネントにコリジョンの設定(オブジェクト応答)をしないと機能しない。
- 注意ではないが、「オーバーラップイベントを発行させる」は有効にしなくてよい。
・SetActorRelativeLocation
Target(Actor Reference)
|
移動させたいアクター(以下ターゲット)を指定
|
New Relative Location(Vector)
|
アウトライナ上で親子関係のある、親を中心(0, 0, 0)とした座標位置を指定。
|
Sweep(Boolean)
|
True のとき有効。ターゲットが物体にぶつかるとターゲットは停止する。
|
Sweep Hit Result(Hit Result Structure)
|
Sweep を有効にしているときに何かにぶつかると Hit Result Structure として返す
|
詳細
Offset 系
・AddActorWorldOffset
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
Target(Actor Reference)
|
移動させたいアクター(以下ターゲット)を指定
|
Delta Location(Vector)
|
ターゲットの現在位置から Delta Location だけ相対座標を軸に移動する。
|
Sweep(Boolean)
|
True のとき有効。ターゲットが物体にぶつかるとターゲットは停止する。
|
Teleport(Boolean)
|
指定した位置に瞬間移動するようになる。
|
Output
Sweep Hit Result(Hit Result Structure)
|
Sweep を有効にしているときに何かにぶつかるとHit Result Structure として返す
|
詳細
プログラミングするときに使うショートカットキー集
- Windows10
- Visual Studio 2017 RC
- Google Search
- Microsoft Edge
Widnows10
仮想デスクトップ間の移動
|
Windowsキー + Ctrl + (← or →)
|
アプリケーションの切り替え
|
Alt + Tab
|
|
|
|
|
|
|
|
|
Visual Studio 2017 RC
タブ切り替え
|
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です。
あまりゲームジャムのことは書いていませんが、参加しようと迷っている方は最後の方だけでも読んでいくと良いかもしれません。
自分は主にプログラム(ブループリント(以下、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などのゲームエンジンを使うゲームジャムに参加するときっと良い経験になると思います。もちろんゲームエンジンを限定していないゲームジャムでも良いです。
特に学生の方は今すぐにでもゲームジャムに参加するべきです。社会人だと今よりも参加しづらくなります。基本土日に開催されると思うので、社会人になるとゲームジャムで丸二日作業して次の日仕事……ってなるので。自分はそれでも人とゲーム開発をしてみたかったので参加しましたが。
学生なら月曜の授業や土日月?のバイトをサボっても良いんです。授業より、数時間のバイトで得た金額よりも必ず得られるものがあります。というのも授業や数千のバイト代はあとで取り返せます。ゲームジャムはその時しかありません。
と、最後に学生の方に向けて書いてみましたが、これは学生のときに何で自分は参加しなかったのだろうと後悔しているからです。一人でゲーム開発をしている方はぜひ参加してみてください。きっと良い日になります。