NinaLabo

個人ゲーム開発者の技術メモ

【Unity】DOTween のインストール

Unityで使えそうなTween系のツールとして、iTween、HOTween、LeanTween などありますが、コードが簡潔に書けるので、個人的には DOTween が好みです。アニメーションのほとんどは Unityアニメーション(Mechanim)で作っていますが、例えばA地点からB地点へ移動するアニメーションがあるとして、B地点がユーザーの入力によって動的に変化する場合などは、Tween系のツールを使って実装しています。

DOTween の読み方

ところで、DOTween って何と読むのが正しいのでしょうか。気になったのでインストール前に調べてみました。
開発者の1人である Daniele Giardini の YouTube を見ると「ドット トゥイーン」と言ってるように聞こえます。ただ、英語は最後のTの発音が弱くなるので、英語の音をそのまま日本語にすると「ドッ トゥイーン」でしょうか。少なくとも「ドゥ トゥイーン (Do Tween)」ではないですね。

DOTween のインストール

《Step1》 Asset Store から DOTweeen を ダウンロード

公式ホームページ(DOTween (HOTween v2))からダウンロードもできますが、アセットストアからダウンロードするほうがインストールが簡単です。

《Step2》ダウンロードした DOTween をインポート

今回、Exampleは必要ないので外していますが、すべてインポートしても大丈夫です。「Import」ボタンを押して、アセットをインポートしてください。

f:id:ninagreen:20151114142420p:plain

《Step3》インポートした DOTween のセットアップ

インポートすると設定画面が自動で立ち上がります。立ち上がらない場合は、Tools -> DOTween Utility Panel で開くことができます。「SetUp DOTween…」を選択して、セットアップを実行してください。実行中に表示されるダイアログはすべて OK で大丈夫です。
f:id:ninagreen:20151114142925p:plain

《Step4》インストール完了!

Step3 までを実行すれば、インストールは完了です。ただ私の場合、インストール時にコンソールログに以下のエラーが出力されました。
 
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> Mono.Cecil.AssemblyResolutionException: Failed to resolve assembly: 'UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'
 
InvalidOperationException: Operation is not valid due to the current state of the object
System.Collections.Stack.Peek () (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Collections/Stack.cs:321)
 
エラーが出るのはセットアップ直後の1回だけで、その後エラーは出ないし、動作にも影響がなさそうなので、ひとまずそのまま放置しています^^
 

 

 

【C#】リストや配列のソート方法まとめ

リスト(List)や 配列(Array)の 並び替えの方法をまとめました。

《CASE1》リスト内のオブジェクトの変数で並び替え

社員オブジェクト(Employee)を格納した 社員リスト(employeeList)があるとして、その社員リストを 社員番号(Employee.ID)で並び替えたい場合
 
【昇順】
employeeList.Sort ((ab) => a.ID - b.ID);
【降順】
employeeList.Sort ((ab) => b.ID - a.ID);
 

《CASE2》リストの値で並び替え 

社員番号だけを格納したリスト(idList)を並び替えたい場合
 
【昇順】
idList.Sort (); 
【降順】
idList.Sort ((ab) => b - a);

 

《CASE3》配列内のオブジェクトの変数で並び替え

社員オブジェクト(Employee)を格納した 社員配列(employeeArray)があるとして、その社員配列を 社員番号(Employee.ID)で並び替えたい場合
 
【昇順】

Array.Sort (employeeArray, (ab) => a.ID - b.ID);

 【降順】

Array.Sort (employeeArray, (ab) => b.ID - a.ID); 

Listとほぼ一緒ですね。Arrayクラスは System パッケージなので、"using System;" を記述しておく必要があります。

 

《CASE4》配列の値で並び替え

社員番号だけを格納した配列(idArray)を並び替えたい場合
 
【昇順】

Array.Sort (idArray);

 【降順】

Array.Sort (idArray, (ab) => b - a);


《CASE5》リスト内のオブジェクトを複数のキー(複合キー)で並び替え

社員オブジェクト(Employee)を格納した 社員リスト(employeeList)があるとして、その社員リストを 年齢(Employee.Age))順の 社員番号(Employee.ID)順で並び替えたい場合。
 
【昇順】
employeeList.Sort ((a, b) => {
    int result = a.Age - b.Age;
    return result != 0 ? result : a.ID - b.ID;
});
2つのオブジェクトの第1キー(Age)の差分を比較して値が同じ場合(差分が0の場合)は、第2キー(ID)での比較判定を行っています。

 

 

【進捗】ゲームが好きとゲーム作りが好きは別物である(2015/11/09)

子供の頃からゲームが好きで、学校から帰ってきたらずっとゲームをして過ごし、社会人になってからも会社から帰ってきたらゲームをしてストレスを発散していました。

そんなゲーム好きなわたしは、自分で好きなゲームが作れるようになったらもっと楽しいだろうなあと安易に考え、個人でゲーム作りを始めた訳ですが、ここ数年はゲーム作りに時間を取られ、ゲームをする時間が減っちゃいました。家には積みゲーがいっぱい。

ゲーム作りをはじめて思うことは、わたしの場合、結局自分で作ったゲームは純粋に楽しむことができないということ。ゲームをたくさん遊んだからといって、面白いゲームが作れる訳ではないということ。そして、何よりゲームをする時間がなくなるということ。

ゲーム作りはゲーム作りで面白いので一応まだ続いてますが、ゲームをプレイする楽しさとは、まったく別物ですね。純粋にゲームを楽しみたいなら、ゲーム作りには手を出さないほうがいいんじゃないかと思えてなりません。

 今週の進捗

  • ダッシュのアニメーションを滑らかになるように改善
  • ゴールドの配置と取得
  • 武器/盾の配置/取得と装備
  • アイテムを投げる

 

 

ローグライクゲームの定義まとめ

最近、ローグを謳っているゲームが増えてきた気がします。ただ、一概にローグと名乗っているゲームでも中身は本当に様々で、不思議のダンジョンシリーズに忠実なものもあれば、死んだら最初からの(または重めのペナルティがある)ゲームをローグと言ったりしているものもあります。

そこで、ローグライクゲームの定義を改めて調べてみました。(ただ、誤解してほしくないのは、この定義に当てはまらないものはローグじゃないというつもりはなく、単に自分でローグライクゲームを開発するうえで、抑えておくべきポイントを再確認しておこうという趣旨です)

ローグライクゲームの定義まとめ

調べてはみたものの、ローグライクゲームの定義について書かれている記事自体が少なく、参考になりそうな記事は2件ぐらいしか見つけられませんでした。

※ ローグライクの定義まとめ | 2dgames.jp

ローグライクの定義にPDLとベルリン解釈があるなんて、はじめて知りました。とてもわかりやすく書かれていて、オススメです。

※ Berlin Interpretation - RogueBasin

前述のリンクにもあるベルリン解釈が書かれた記事です。International Roguelike Development Conference(IRDC)(日本語にすると、国際ローグライク開発会議でしょうか...)というところで話し合われたローグライクの定義だそうで、英語ですが興味あるかたは是非。

ローグライクゲームを構成する重要な要素

前述のベルリン解釈を参考に、現在開発しているローグライクゲームに組み入れるべきと個人的に思う、重要な要素を列挙しました。

1. 環境の自動生成(Random environment generation)

モンスターやアイテムの配置をランダムにする等、ゲーム内のステージをランダムに生成し、繰り返し何度遊んでも楽しめるようにすること。

2. 恒久的な死(Permadeath)

ゲームオーバーになったら、最初のレベルからやり直す。それが制裁や苦痛などではなく、楽しさになるようにすること。

3. ターン制(Turn-based)

 じっくり考えて最適な行動を選択できるように、リアルタイム制ではなくターン制にすること。

4. 複雑性(Complexitiy)

ゴールに到達するまでに複数の最適解があるようにすること。十分なモンスターとアイテムがあり、それらが相互作用することによって得られる良い意味での複雑さを持つこと。

5. リソース管理(Resource management)

食料や回復薬などの限られた資源をうまくやりくりしながら、ゲームを攻略する楽しさを提供すること。状況に応じた最適な資源の活用方法を考える楽しさを提供すること。

 

探索と発見(Exploration and discovery)も入れようか悩んだのですが、マップをワクワクしながら探索して新しい発見をするというよりは、手持ちの資源を駆使して、困難な状況をうまく切り抜けるほうを重視したかったので、一旦はずしました。

開発を進めていくと、いろんな仕様のアイディアが思いつくのですが、考えなしに採用していくと最初に提供したかった楽しさがわからなくなっていくので、自戒の意味も込めてこの5つはブレないようにしようと思います。

 

【C#】数値を符号(プラス/マイナス)を付けた文字列に変換する

たとえば・・

数値がプラスの場合は、

「こんぼう +1」

数値がマイナスの場合は、

「こんぼう -1」

数値がゼロの場合は、

「こんぼう」

と表示するとします。

 

もちろん、if分で場合分けして、文字列を組み立てればできるのですが、

string.Format ("{0} {1}"itemNamenum.ToString ("+#;-#;"));

と書けば、1行で済みます

(itemNameはstring変数で"こんぼう"を、numはint変数で数値が設定される想定) 

 書式の解説

num.ToString ("+#;-#;") が、わかりにくいと思うので、少し補足。

;(セミコロン)で区切られた左から、数値が正(プラス)の場合の書式、数値が負(マイナス)の場合の書式、数値が0(ゼロ)の場合の書式です。

この方式の場合、#には符号なしの数字が入るので、数値がマイナスのときにも-(マイナス)を記述しています。数値が0のときは何も表示しないので、2つ目のセミコロンの右側は、何も記述していません。

 

 

 

 

【進捗】モチベーションの低下は突然やってくる(2015/10/25)

開発する前はあんなにあったモチーベションが、急速になくなっていく... わたしの場合は開発1ヶ月〜開発2ヶ月ごろに、第一陣がくるようです。

1. 単純に飽きてくる

特に実装作業をしていると、ゲームを起動しては動作確認して、停止してコーデイングして、を気が遠くなるような回数繰り返すので、どんなに面白いゲームを作っていたとしても飽きないことはないような気がします。

2. 頭の中でイメージしていたものと現実とのギャップが出てくる

開発前の頭の中のゲームは、それはもうめちゃめちゃ面白いゲームなのですが、ちょっとずつ出来上がってくると、「あれ、もしかしてこのゲーム、そんなに面白くないんじゃ・・?」と不安になってくるのがこの時期なのかもしれません。

3. 他のゲームがとても良く見えて、自分のやっていることが無意味に思えてくる

そして、ちょっと不安になってきた頃に、App StoreやWeb記事等で他のゲームのことが目に入ってしまうと、それが自分より遥かにクオリティが高くて遥かに面白いゲームに見えて(実際、すごいゲームが多いのですが)、自分がいくら頑張ったところで敵わないし、もうやめたほうがいいんじゃないか、と思えてきます。

4. 進捗が感じられなくなってくる

そんなこんなで、不安になりながら実装しているので、だんだんと開発スピードが遅くなっていきます。それに加え、開発初期はゼロからのスタートなのでどんどん積み上がっていくのが楽しいのですが、だんだん調整項目やバグ修正、バックエンド処理も増えるので、目に見える進捗が減っていき、負の連鎖に陥ってしまいます。

対処法

わ、わかりません....

できれば、1ヶ月〜2ヶ月で集中して実装してリリースしてしまいたいですが、本業の仕事もあるのでなかなかそうもいきません。

あんまり偉そうなことはいえませんが、現時点では、なるべく簡単な作業を少しだけやること、そのかわり毎日やること、を心がけるようにしています。無理してたくさんやろうとしたり、高い集中力が必要な複雑なことをやろうとしたりしない。調べないとわからないような難しいことも、この時期はやらないようにしてます。絶対挫折する自信があるので(笑)

あとは偉大な人の名言でも見て、心を癒すぐらいでしょうか・・イチローさんもこう言ってますしね。

「やれることはすべてやる」それを毎日継続して行うのは一番苦しいことであり、とても大変なことである。
 
でもそれさえちゃんとしていれば、結果が出てない時でも後悔せずに満足できる。
 
小さなことを積み重ねることが、
とんでもないところに行くただひとつの道だと思う。 

 

 今週の進捗

  • モンスターの種類ごとに画像を差し替え
  • アイテムを拾う
  • 所持アイテム一覧からのアイテム詳細を見る
  • アイテムを使う、アイテムを置く(アイテムを投げるは間に合わなかった..)

 

 

【Unity】GameObjectをSetParentするとエラーになる件

エラー内容

Setting the parent of a transform which resides in a prefab is disabled to prevent data corruption.

この時点では何のことなのか、さっぱりわからず...

エラー箇所

 gameObj.transform.SetParent (baseTransform);

子のゲームオブジェクト(gameObj)を、親(baseTransform)に設定している箇所

 gameObj.transform.parent = baseTranform;

この書き方でも一緒のはず。昔はこう書いてましたね。

解決方法

結局単純なコーディングで、プレハブをInstantiateしていないだけでした...

以下のように、プレハブのオブジェクト(prefabObj)をInstantiateしたゲームオブジェクト(gameObj)を親に設定しているつもりでしたが...

GameObject gameObj = Instantiate (prefabObjas GameObject;

prefabObjをそのまま親オブジェクトに設定しようとしていました...orz

 

以下の記事を見て、自分の凡ミスに気づきました。

From the error, it looks like you're not instantiating prefabs before you give them their parents. The error basically means that you can't change the parent of a non-instantiated prefab.

まさにこの人、ずばり言い当ててますね。