【Unity】c#の例外処理、その使い所

個人的にあまり詳しくない「例外処理」について調べてみました。 「try{} catch{}」を使うのが例外処理なのだな、というぼやけた認識でいるのですが、具体的にどういった場面で利用するのかなど実践で使えるのか、処理は重くないのかなど考えてみました。

例外処理

「try{} catch{}」を使って簡単な例外処理を書いてみます。 次のコードはDictionaryのkeyが不正だった場合に例外処理を行うようにしました。 [c] void Start() { dict = new Dictionary<string, string>(); dict.Add("hoge", "ほげ"); dict.Add("start", "スタート"); dict.Add("end", "エンド");

    // 処理
    try
    {
        Debug.Log(_dict[&quot;hogo&quot;]);
    }
    catch()
    {
        Debug.LogWarning(&quot;例外が発生しました&quot;);
    }
}

[/c]

tryの中のスコープ内で例外処理が発生した場合、catchのスコープ内の処理が呼び出されます。 通常ですとKeyNotFoundExceptionが発生しますが、これを回避することができます。

なお今回の処理は普通なら通常は次のようなコードを書くため例外処理を必要ありません。 [c] // 普通の処理 string text = string.Empty; if(_dict.TryGetValue("hoge",out text)) { Debug.Log(text); } [/c]

例外ごとにcatchの処理を分ける

例外の種類ごとにcatchの処理を分けることができます。 [c] try { Debug.Log(_dict["hogo"]); } catch(KeyNotFoundException e) { Debug.LogWarning(e); } [/c]

catchは一つだけではなく、複数書くこともできます。

finally

「try{} catch{}」にfinallyをつければ、例外が出る・出ないにかかわらず実行される処理を書くことができます。 [c] finally { Debug.Log("最終的処理"); } [/c]

throw

throwを使うと該当箇所に例外を投げることができます。 [c] string hoge = string.Empty; if (_dict.TryGetValue("end", out hoge)) { Debug.Log(hoge); } else { throw new KeyNotFoundException(); } [/c]

いろいろ調べてのですが、throwをどの場面で使った良いのかはわかりませんでした。 別に例外を投げなくてもログを吐けばよいのではと思います。

例外の使い所

ざっと調べてみて、例外処理に関してはこちらが注意をすれば実装しなくても良い場合が多いと感じました。 よく見かけるエラーログはNullReferenceExceptionで、これはNullチェックを念入りに行えば回避することができますし、例で上げたKeyNotFoundExceptionなども人為的な実装ミスになるので、事前に何かしらの判定を入れて回避が可能だと感じました。

ではどこで使ったらよいかと考えると、実装以外の何かしらの不備が発生する箇所です。 具体的には、AssetBundleを含む外部からデータのダウンロードする際になります。 データそのものがない場合は論外ですが、例えば通信不備で本来あるはずのAssetがない場合などです。 いくら実装を正しく行ったとしても起きる可能性がある現象で、このような場合に例外処理を使うのではないかと思いました。(例外が出たら再度読み込む処理をする、もしくは通信エラーのダイアログを出すなど) 普段はそういった通信周りを関係ないことをしているので「例外処理」はあまり馴染みがないのだと同時に感じました。

【Unity】コードを共通化して負債を減らす

Unityだけではないと思うのですが、コードを書いているときに同じような処理を書く必要が出てくる場合があります。 何も考えずに、コードをコピーすればこの問題は解決するのですが、将来的には負債を残すことになります。 時間的な成約がなにもないのであれば速やかに共通化し同じコードを使い回すように設計すれば、今後のもし変更が入ったときに対応が簡単になります。

通化のメリット

通化することはメリットしかありません。 同じコードを書く必要がなくなりますし、修正をしようとしても一箇所だけです。

  • 修正が一箇所だけなので楽
  • 同じ処理を記述しなくても良い

メソッド化

クラス内に複数同じ処理があるのであれば、それをメソッド化して使いまわします。 個人的に2つ以上同じような処理を記載するとなった場合メソッド化したほうが良いです。 [c] private void CommonHoge() { // 何かしらの処理 }

private void Hoge() { // 各メソッドで使い回す CommonHoge(); } [/c]

Baseクラス作成

似たような機能を作るときにはBaseクラスを作り、共通化できる処理を記述すれば使いまわして利用できるようになります。 [c] public class BaseClass { protected void CommonHoge() { Debug.Log("共通化"); } }

public class AClass : BaseClass { private void Start() { CommonHoge(); } }

<h2>インターフェイス</h2> Interfaceを使ってクラスの処理を共通化することもできます。 Interfaceは特定に挙動を保証する仕組みで、interfaceで定義されたメソッドなどを継承元のクラスに記載をします。

[c] public interface IInterfaceClass { void GetNumber(); }

public class AInterfaceClass : MonoBehaviour, IInterfaceClass { private int number = 10; public void GetNumber() { Debug.Log(number); } }

public class BInterfaceClass : MonoBehaviour, IInterfaceClass { private int number = 5; public void GetNumber() { Debug.Log(number); } } [/c]

Interfaceで定義されているメソッドは継承先のクラスにかかわらず呼び出すことができます。 [c] private void Start() { AInterfaceClass aInterface = new AInterfaceClass(); BInterfaceClass bInterface = new BInterfaceClass(); var list = new List<IInterfaceClass>(); list.Add(aInterface); list.Add(bInterface);

  foreach(var obj in _list)
  {
      obj.GetNumber();
  }

} [/c]

ユーティリティクラスを作成

横断的に利用する場合、staticなクラスを一つ用意し、その中に共通な処理を記載します。 [c] public static class Utility { public static void SetDebugLog(int num) { Debug.Log(num); } } [/c]

色々なところから呼び出せます。 [c] void Start() { Utility.SetDebugLog(10); } [/c]

staticなクラスはオブジェクト指向と相反するなど利用に否定的な見方があるかもしれませんが、適切に利用すれば同じ記述を使い回さずにすみます。

キングダムハーツ3をクリアしました。

先週末にPS4ソフトの「キングダムハーツ3」をクリアしました。 クリアまでのプレイ時間は22時間ほどで、2週間くらいかけて遊ぶことができました。 簡単ですが、ブログに感想を書いていきたいと思います。

2019 03 10 1

キングダムハーツ

前作から10年以上空いての続編ということで、キャラクターの名前くらいしか覚えていませんでした。 ただ、1と2はとても面白かったという記憶はあったので、続編がいつ出るのかはとても気になっていました。

ゲーム内容

キングダムハーツシリーズは「スクウェアのキャラクター × ディズニーのキャラクター」が登場するアクションゲームと記憶しています。 主にディズニーシリーズの世界を、主人公が旅をするのですが、そこにファイナルファンタジーのキャラクターが絡んできているという内容です。 私は、この作品だけではなく別作品同士がコラボするということにとても興奮を覚える性格でしたので、このコラボレーションがキングダムハーツシリーズの最大の魅力だと思っていました。

本作品では、ディズニーのキャラクター以外にもピクサー社の世界も登場します。 このあたりは、前作までにはなかったことで、この長い空白期にディズニーとピクサーが一緒になったことも影響しているのではないかと思います。

感想

とりあえずやり込みの要素や今後登場するであろう追加コンテンツは別にしてEDまで見た感想をここから書いていきたいと思います。 もしかしたらネタバレになる可能性があるので、まだ未プレイの方は注意してください。

ボリューム

22時間でクリアできましたので、EDまでのボリュームはあまりないと思います。 レベル上げも特にしていないので、普通に進んで行けばそのまま最後までいけるレベルバランスです。 そもそも、このキングダムハーツシリーズはこれまでのボリュームにあるゲームではなかったので適切な内容量だと思います。

グラフィック

PS4作品ということもあるのですが、これまでの作品と比べてとてもキャラクターや世界背景は綺麗です。 PSProですと更に映像が良くなるみたいです。 そもそもリアルな世界観ではないため、そこまで作り込みは必要ないと思うのですが各ストーリーの正解感がそのまま表現されているようでした。 特に「トイ・ストーリー」の世界が好きで、キャラクターなどは本当にアニメの世界そのもので感動しました。

2019 3 10 3

システム

アクションゲームというこで、攻撃ボタンと移動がメイン。特殊なアクション時には該当のボタンを押せば発動されます。 基本攻撃ボタンを連打するゲームだと思います。魔法も使えるのですが、回復魔法しか使わなかったです。 主人公の武器に応じて特殊な攻撃ができるので、本来なら場面場面で切り替えて使うのだと思うのですが、最終で気に一番攻撃力が高い武器しか使わなくなりました。

今作品から壁を登ぼることができようになり、アクションがいくつか増えましたが、オープンワールドとはまではいえず行動できる範囲は決まっていますし、できることも限られています。 良く言えば操作が簡単、悪く言えばあまり技術を必要としません。 キングダムハーツシリーズはストーリーを楽しむゲームな気がするので、このシステムで良いと思いました。

登場人物

これまでの主人公(ソラ)と外伝シリーズのキャラクターが一同に登場します。 ただプレイアブルキャラクターは一部に限られています。 また、話の中でこれまでのストーリーについて触れられている部分はあるのですが、そのあたりは既に知っているものとして話が進んでいきます。 ですので、過去作品をやっていないと話についていけない恐れがあります。

ストーリー

8つの世界を回るのですが、各世界の話はとても面白かったと思います。 主人公とその世界のキャラクターがうまく絡み合っていた気がします。 特に、トイ・ストーリーパイレーツ・オブ・カリビアンの世界は楽しかったです。

2019 3 10 2

ただ残念な点が2点あります。

強制ストーリー

キングダムハーツシリーズがこういった作品なのであれば仕方がないのですが、強制ストーリーが多すぎる気がしました(特に最後の方) 本来ならプレイヤーが動かして戦うのであろうとおもった場所でも、強制ストーリーで終わらせてしまったりするのはガッカリしました。 また、このストーリーはスキップすることができないです。 日本のRPGの悪い点としてこの強制ストーリーがあると思うのですが、適度に登場するのであれば良いと思います。ただ、本作品は多すぎた感じです。 映画を見たいのではなく、遊びたいと思ってゲームをやっているので、プレイヤーの操作できない部分を多くしていただきたいと思いました。

コラボ

本作で私が一番不満に思ったのが「ファイナルファンタジースクウェア)」側のキャラクターや一人も登場しなかった点です。 1,2までは出ていたので、今回はFF13FF15のキャラが出てくると思ったのですが、これまで登場したキャラも含めて出てきませんでした。 このシリーズに興味を持ったきっかけが、FFのキャラがディズニーのキャラと登場するということだったこともあるので、私が遊びたいと思う動機がなくなってしまいました。

もう一つ、最後のバトルあたりで、これまで巡ってきた8つの世界がまったく絡んでこなかったのも不満です。 8つの世界と最終決戦は完全に別々に分かれていて、そもそも8つの世界を回る必要があったのかと思いました。

最後に

本作品について8つの世界とグラフィックはとても良かったです。 ただ、ストーリー面をもう少し改善してほしいと思いました。

【Unity】コルーチンの制御

Unityでコルーチンを使って処理の流れを制御する時の待機方法を調べてみました。 通常はWaitForSecondsを使っている感じなのですが、その他色々な方法があります。

コルーチンの制御

コルーチンについてのドキュメントはこちらです。 コルーチン - Unity

秒数待つ

指定された秒数を待機する時にWaitForSecondsを使います。 [c] private IEnumerator StartAction() { yield return new WaitForSeconds(1.0f); } [/c]

時にはタイムスケールを制御している場合があるときにはWaitForSecondsRealtimeを使います。 タイムスケールに影響されずに待機することができます。 [c] private IEnumerator StartAction() { yield return new WaitForSecondsRealtime(1.0f); } [/c]

WaitUntil

指定した条件を満たすまで待機するのがWaitUntil()です。 [c] private IEnumerator StartAction() { yield return new WaitUntil(()=>_count > 10); } [/c]

WaitWhile

指定した条件から外れたときまで待機するのがWaitWhile()です。 [c] private IEnumerator StartAction() { yield return new WaitUntil(()=> gameObject == null); } [/c]

自作する

CustomYieldInstructionを継承すれば自作の待機処理を作成することができます。 必要なプロパティはkeepWaitingです。 こちらの条件を見てコルーチンを待機させることができます。

[c] public class CustomHoge : CustomYieldInstruction { public bool IsComplete { get; private set; }

public override bool keepWaiting
{
    get { return IsComplete == false; }
}

}

private IEnumerator StartAction() { yield return new CustomHoge(); } [/c]

最後に

コルーチンは今後、「async await」に置き換わっていくと思うのですが、コルーチンはまだまだ健在です。 今回調べて、色々な使い方が見えてきましたので、実際に使える場面で使っていきたい。

「ワンフェス2019冬」に行ってきました【フィギュア】

2月10日に幕張メッセで行われた「ワンフェス2019冬」に行ってきました。 ワンフェスには毎年夏に時間があれば言っていたのですが、今回は初めて冬開催に行ってみました。 ワンダーフェスティバル|Wonder Festival

ワンフェス

ちょうど9時50頃に幕張メッセに着きました。 前回訪れた夏に比べて到着時間は遅いのですが、待機列は比較的前の方でした。 それでも入場までには開場時間(10:00)から30分くらい遅れてになってしまいました。 2019 2 25 01

仮面ライダージオウ

個人的に仮面ライダーが好きなこともあるのですが、メディコム・トイの仮面ライダーシリーズはとても良くできていると思っています。 最新作である仮面ライダージオウが展示されていましたが写真写りもよくとてもかっこよく撮れていたと思います。

艦これ

グッドスマイルカンパニーブースでは過去、艦これだけのブースがあったのですが、今回はその他大勢のように展示されていました。 時代の流れと注目度の影響を感じます。 私自身、艦これをもうやっていないのですが、今回展示されていたフィギュアはギリギリ知っているものでした。

ゴブリンスレイヤー

去年の秋のアニメで結構ハマったのが「ゴブリンスレイヤー」です。 まだ早いかと思っていたのですが、原作絵のフィギュアが並んでいました。 この2人が人気なのかなと思いました。

ゆるキャン△

ゆるキャン△の人気はとても高いなと今回のワンフェスを見て感じました。 複数の企業から出ているのもあるのですが、アマチュアのブースでもたくさんのフィギュアが並んでいました。 主人公のなでしこのフィギュアは前回余りなかったので今回写真撮影ができてよかったです。

ssss.gridman

フィギュア業界が流行に敏感なことがよくわかるのが、「ssss.gridman」の出店の多さだと思いました。 どれも当初から企画されたものではなく、アニメが流行っていることを理由に企画されたものだというのが、着色済みのフィギュアが一体もなかったことから想像できました。 おそらく夏頃から販売されるのだと思いますが、色がのることでどういった形になるのか楽しみです。

2019 2 25 02

HUNTERXHUNTER

HUNTERXHUNTERの蟻編、メルエムvsネテロ会長がフィギュア化されていました。 3Dの百式観音がどういった感じなのか、これは直接見ていただいたほうがよいのですが、結構マニアックなシーンをフィギュア化したなと思います。

ガルパン

今年の5月の劇場版が出るのですが、コトブキヤのフィギュアがとても良くできていました。 ガルパンの凄いところは主役ではない脇役や敵キャラも等しく人気があるところで、今回のワンフェスでは逆に大洗高校(主人公)側のフィギュアは一体もなかった気がしました。

SHIROBAKO

今までなかったのかと思いましたが、SHIROBAKOねんどろいど。 劇場版の公開が決まったということもあるのか、この時期で発売されるみたいです。

最後に

今回マクロレンズを使って撮影をしてみたのですが、結構キレイに撮れているなと感じました。 ただ倍率が35mmの単焦点レンズですので、細部にわたって撮影するのは難しかったです。もう少し倍率のあるレンズが欲しくなりました。

レッド・デッド・リデンプション2をクリアしました

先月から少しづつ遊んでいたPS4ソフト「レッド・デッド・リデンプション2」をクリアしました。 去年に発売し、結構話題になっていたソフトなので遊んでいる方は多いのかもしれませんが、とても面白かったです。

レッド・デッド・リデンプション2

2010年に「レッド・デッド・リデンプション」が発売されているのですが、私はこのシリーズを遊ぶのは初めてです。 話のつながりは特にないそうなので、いきなり2からはじめても問題ないです。

ゲーム内容

ゲーム内容は「オープンワールド」ゲームです。 メインのイベントを主軸として、サブイベントや探索や賞金首など色々なことができます。 移動手段は馬です。ファストトラベルは使えるのですが、主要な街にしかいけないこともあるのであまり利用頻度は高くありません。

感想

とりあえず進行度が100%になったので、そこまでの内容を加味して感想を書きたいと思います。

ボリューム

メインイベントがとても多いと感じたので軽く100時間以上遊ぶことができました。 ストーリーも単調に敵を倒すだけではなく、内容に波があるのでどれも楽しめました。 イベント以外にも様々な探索もあるのですが、私はほとんどできませんでした。 今後の追加コンテンツもありそうな感じですので、長く遊ぶことができると思います。

グラフィック

レッド・デッド・リデンプション2」はディスクが2枚入っています。 データ用とゲーム用です。それだけデータ量があるということです。 そのデータ量が示すように、グラフィックはとても綺麗です。 主人公のモデルのアニメーションも3Dだなと違和感を持たれないくらい精巧にできています(モブキャラはそうでもありませんが、) この美しい世界を見て回るだけでもこのソフトをやる価値があると感じました。

システム

システムはオープンワールドでよくあるゲームシステムなのですが、「レッド・デッド・リデンプション2」で面白いと思ったのは、ライフとスタミナに空腹度が絡んでくることです。 なにか食べないと痩せていきスタミナがなくなります。逆に太り過ぎるといったこともあります。 また、寝ないとモノを食べてもスタミナが回復しません。

また良い行いをすると評判があがり、悪行を繰り返すと評判が下がる評価システムがあり、イベントだけでなく、普段の行動時にどうするかを慎重に選ぶ必要がありました。

登場人物

仲間のキャラクターが多いので最初はどういった人物なのかわからないですが、とにかくイベントが多く色々なキャラクターと絡みが増えます。 そのため、どういった人物なのか段々とわかってきます。 そういったこともあり、ゲーム後半では結構キャラクターに愛着が生まれきました。

バトル

操作がとても複雑です。 オープンワールドは特にそうなのですが、色々できる反面プレイヤーの操作が簡単ではありません。ですので、操作ミスで他人の馬を盗んでしまったり、馬車に飛び乗ったりして指名手配されるなど、位置した行動ができないことが多々ありました。 これは慣れてくるとマシになるのですが、どうも序盤が大変です。

最後に

前評判通り、とても面白かったです。 ストーリーもとても良かったので、操作方法や移動手段に難儀しながらも最後まで遊ぶことができました。 西部をストーリーにするゲームをやったのは初めてだったのですが、歴史がどうなっていたかを学ぶこともできた気がします。 また、英語音声しかないこともあり、字幕と照らし合わせて、英語の勉強にもなった気がします。

【Unity】UnityのAttributesを調べてみた

個人的に一度調べてみたかった属性についてブログに書いていきたいと思います。いろいろな制約や拡張ができるので、上手く組み合わせて使えば作業速度や効率が良くなると思います。

Attributes - 属性

クラスに成約をもたせることができます。

RequireComponent

指定したクラスが必要になります。 例えばTextクラスが必ず必要な場合には次のような記述を行います。 [c] [RequireComponent(typeof(UnityEngine.UI.Text))] public class Hoge : MonoBehaviour {

} [/c]

もし必要なクラスがない場合にはダイアログが表示されます。 2019_02_14_memo

SerializeField

Inspector上のprivateのフィールドを設定できます。(これをシリアライズ化とも呼ぶらしい) Publicでも同じようなことはできますが、他のクラスから参照ができてしまうので、限定して利用したい場合に使います。 [c] [SerializeField] private string hogeText; [/c]

2019_02_14_memo2

AddComponentMenu

「AddComponentMenu」メニューのComponent」に特定のクラスを指定する場合に利用します。 次のコードでは「Hoge、AddComponentMenu」に追加します。 [c] [AddComponentMenu("Hoge/AddComponentMenu")] public class Hoge : MonoBehaviour {

} [/c]

画面上では次のようになります。 2019_02_07_03

ColorUsage

アルファを設定できるかどうかを調整できます。 ColorUsage

[c] [ColorUsage(false)] [SerializeField] private Color _color; [/c]

アルファの項目が無くなっています。 2019_02_15_moem

ContextMenu

ContextMenuを設定すれば、Inspector上で右クリックを押すとメソッドを実行できるようになります。 [c] [ContextMenu("Test")] public void Test() { Debug.LogError("Test"); } [/c] 2019 02 15 memo2

ContextMenuItem

ContextMenuItemは指定したフィールドで右クリックをすると、引数で指定したメソッドを呼び出せます。 ContextMenuItem - Unity Documentation

[c] [ContextMenuItem("Test","Test")] [SerializeField] private Color _color; [/c] 2019 02 15 memo3

DisallowMultipleComponent

DisallowMultipleComponentは同一のコンポーネントをアタッチできなくします。 [c] [DisallowMultipleComponent] public class Hoge : MonoBehaviour { } [/c]

参考サイト

UnityのAttribute(属性)についてまとめてメモる。