2016年12月10日

Unityでゲーム初めて作った(「ゆにぜに!」)

部品ばっかり研究していたのですが、ようやくひとつ完成品ができましたよ。 作品紹介ページはたぶん別に作るので、これは作ったときに苦労した点や気づいた点などのメモ。

http://www.nscripter.com/UniZeni.zip

2016-12-09.jpg2016-12-07.jpg

3D迷路を走り回り、4種類ある罠をかいくぐりコインを集めるジャンプアクションゲームです。いろいろ勉強になりました。そこそこ遊べると思いますが、これは練習作のつもり。次から本気で収益化を狙った作品を作っていきますよ。まずはAndroidで無料広告モデルだ。
さて、このゲームの反省点について。

  • MoonSharpを使ってスクリプティングしてるんだが、このゲームではほとんど意味がない。ああいうのはADVとかで威力を発揮するものだ。多分次の作品で本格的に使う。
  • StandardAssetの出来合いのコンポーネントとやりたいことの埋め合わせに主に苦労した。まあ、ソースもあるしアセットフォルダに入るのはコピーされたファイルだし、いざとなったら解析して改造すればよい。ただ、TPSコントローラはたぶん次は自分で作ると思う。
  • マップはJSONから読んでオブジェクトを配置しているのだが、元々は読み込み実験がしたかっただけだったので、Unityのレベルエディタ上で作ったほうがいろいろリッチなものが作れるだろうとは思います。
  • ガチの3D迷路にしてしまったため、敵キャラを入れるのとかはちょっとゲーム性的に難しそうで断念した(これだと視界がほとんどないし、攻撃手段が踏むだけだとかなりヤな感じになりそう)。
  • ユニティちゃんが弾き飛ばされる演出でRigidBodyで計算して速度を与えて実装しようとしたけどどうも思うようにいかず、結局Transform.Translateで動かしたら一番すっきりした。加速度運動くらいなら時間との関数で簡単に書けるしね。
  • ふっとばされたユニティちゃんがダメージモーションの際に壁にめり込む問題の解決。弾き飛ばされてる間はTPSコントローラに最初からついてるカプセルコライダーをenabled=falseにして止め、お尻のTransformにつけたボックスコライダー(頭のほうまで大きめに入るようにしてある)をオンにして判定しうまくいきました。ちなみに両方オンにすると自分のコライダーに引っかかって動けなくなるみたい。レイヤを使って回避することもできるっぽい雰囲気だが今回は単にオンオフで対応。
  • 今回スキンメッシュはユニティちゃんのみ。あとはTransformを時間でアニメーションさせてます。不気味多面体や三面の壁や空の色アニメはマテリアルからシェーダーに変数を設定してます。このシェーダーの変数名については、公式サイトからシェーダーのソースを落とせるのでそれを解析すればだいたいわかる。
    補足:Animation Clipでもシェーダー変数含めだいたいのものはアニメーション出来るので、後でUnityエディタが他のツールからの使用をサポートしてくれる可能性を考えるとそっちで書くべきか。iTweenもループも含めだいたいのことはやってくれるので使用を検討。スクリプトで書くのは(コード量は小さいとはいえ)悪手かも。
  • モデルはほとんどプリミティブそのままなのが多いけど、テクスチャは3D-CoatやSubstancePainterの練習だと思って多少頑張ってみた。あとはIllustratorとPhotoshopかな。レベルエディットはTiled Map Editor、そのために使うマップチップ作成にはEDGEを使用しました。
posted by NTak_Indies at 14:31| Comment(0) | TrackBack(0) | 日記

2016年12月02日

モデリング練習

マイクラで作ったこの家を

2016-11-30_07.06.38.jpg

MinewaysでOBJファイルに変換し、それをMayaLTに取り込んで、これをテンプレとして家をモデリングし

2016-11-30.jpg

適当に塗ったわけだが……なんだこれ……w

2016-12-02.jpg

とりあえず、オブジェクトを分けることでUVはなんとか触れそうだけど、テクスチャがまだどうにもならないなあ。屋根とか壁とかもうちょっと使いこなさないと作れなさそうだ。あるいは写真撮って来てそれ使ってもいいけど。

posted by NTak_Indies at 02:02| Comment(0) | TrackBack(0) | 日記

2016年11月28日

Unity+MoonSharpで開発を進めている

Unity+MoonSharpで開発を進めている。

現在、次のようなLuaスクリプトが動かせるものが出来ている。


function main()
  表示文です。
  [名前タグ]はろーわーるど。
  >english print text.
  -- 下の二つは同じ意味
  [tag]text
  >[tag]text
  log("普通のLuaの記述")
  local x=0
  for i=1,10 do
    foo(i)
  end
end

NScripter系と同じ仕様の表示文を


___p("名前タグ","はろーわーるど")
というように行を一対一対応で置換して実行する。いわゆる外部DSLというやつだが、こうすることでLuaの文法に最小限の拡張をしてゲームのシナリオを記述できるようになった。Luaのエラーメッセージも行番号にズレがないのでちゃんと正しい場所を返してくれる。

ここからしばらく、勘違いで必要のなかった作業についての記述なので折りたたんでおきます。ただ、ビルド前処理の練習にはなりました。

問題はこのファイルの拡張子を.luaのままにしておきたいということだ。.txtにしたり.bytesにしたりすると、テキストエディタのシンタックスハイライト機能が効かなくなるからだ。
しかしUnityは元々登録されている拡張子のリソース以外は読み込んでくれない。StreamingAssetsにしておけば生ファイルを扱えるが、スクリプトファイルがそのままコピーされてしまうため、さすがにゲームのコードをダブルクリックでそのまま読めてしまうのは具合が悪い。そこで次の方法でとりあえずの解決を見た。

  • Assets外のフォルダにluaファイルを置いて、そこで編集し、「再生ボタンを押した時」もしくは「ビルド前」にAssets/Resourcesにテキストアセットの拡張子に変換したものをファイルコピーし、インポートさせる。コードからはこのテキストアセットのほうを読み込む。[PostProcessScene]を使って実装した。

(疑問点)再生ボタンを押すごとにluaスクリプトリソースがフル更新されるんだけどこういう設計でいいのか? また、このタイミングでリソース更新をかけた場合確実にリソースが更新されることは保証されているのか?
(考察)元々再生時にシーンまるごとメモリに読み込んでバックアップしてるようだし、これくらいはどうってことなさそうな気もする。リソースの更新についてはどうなんだろう。各アトリビュートのついた関数の実行タイミングが、リソースを追加していいタイミングなのかどうかってどこかで分かるんだろうか? とりあえず今のところ大丈夫のようだが。

ひとまず何か一本作ってみないと分からないかもしれない。この後簡単なギャルゲADV風のサンプルシステムを組んだら、何かゲームを一本作る。

(注釈)その後、たとえばAtomでは「Select Grammer」で、テキストファイルを開いたときでも文法をLuaで認識させることが出来るのが判明しました。これならもうテキストアセットでいいや……ただ、ビルド前やエディタ実行前に何かやる、という処理を書くのに役には立つのでいい経験になりました。

セーブロードの仕様について検討

セーブロードの機構をどうするかも悩み所。Luaの実行状態はセーブ出来ないからだ。ギャルゲADV以外では「シーンの冒頭まで巻き戻る」か、いっそ「宿屋やロビー画面でしかセーブ/ロードはさせない」で解決する(むしろそうしない場合、撤退できないイベントや場所で絶対に敵に勝てないレベルでセーブされると詰む、みたいな状況が頻発するので慎重な作業が必要になる。あと、特に3Dとかアクションゲームとかの場合、ゲームの実行状態を全部完全に保存するのが現実的でないこともしばしばあるので)。 ただ、ギャルゲ系の読み物ADVはどうしても、読んだところでちゃんとセーブして次はそこから始まって欲しいという需要がある。シーン単位だと、そのシーンが長大な時にかなり巻き戻ることになるからだ。これを実装するのは生のLuaスクリプトでは無理で、別のスクリプト言語が必要になると思われる。NScr2で言えばBASICだし、吉里吉里で言えばKAGだろう。この部分の文法をどうするか。うーん、やはりギャルゲADV界隈はどうしてもどこかで俺俺言語のくびきを逃れられないのだねえ。

今回のテーマは疎結合

正直NScr2のBASICはリッチすぎる。RPG風戦闘シーンとかミニパズルゲームまでこのBASICで組んじゃってるわけだが、そういうのは本来LuaやC++(Unityの場合ならC#)でやるべきだ。スプライトシステムがBASICの記述に最適化されているためBASICでやれることはBASICでやってるのが現状だが、今作ってるUnityのスクリプト環境のほうでは、「疎結合」をテーマにしたい(名前もLooseScriptにしようかなとか思ってる)。UnityはVisualC++でDirectXで組んでるときとは違い、アセットもコンポーネントもUIエディタも充実していて、こちらで組んだ方がLuaや自前言語で組むよりむしろ楽だし、JITの効くC#のほうが絶対に実行が速い。なので、そういう複雑なゲーム的な部分はUnity側で組んで、Luaやシナリオスクリプトはそれを大まかに制御するだけにしたいのだ。だから、シナリオ部分をスクリプト言語にするとしたら、出来るだけシンプルなタグ付けだけのものにしたい。その上で、演算したい場合はLuaコードをHTMLで言うscriptタグみたいな感じで呼べるようにするかな。

今回作ってるエンジンの方向性について。

一年以上グダグダ作っては作り直してますが、そろそろこれは形にする。相当ブラッシュアップされてきたので。
ひとまず、サンプルのADV環境は提供するけど、カスタマイズは生Unity環境でやるようなものになると思う。UnityのGUIエディタやC#スクリプトは使ってもらうし、ビルドプロセスはUnityのものになるので。「宴」ほどには統合環境的ではなく、あくまでプラグイン的な立ち位置。初心者には難しいかも知れない。その分生Unityに近く、疎結合で柔軟なため、SpineでもLive2Dでもなんでも、よそのコンポーネントは使い放題になると思う。
まあ、まだ出来てないようなものの青写真はともかくとして、うちの業界はクロスプラットフォーム開発環境への以降をぼちぼち考えはじめてる人も増えてるはずで、その流れに乗りたいです。
配布形態はオープンソースにして導入作業やサポートを引き受けた時にお金取るか、あるいはアセットとして売るか……お金は欲しい、のだが、今世の中見てると、もうエンジンそのものを売って商売するのは難しくなってきてる。だから組んで仕事出来る人が現れそうなら前者でいいかもしんない。名前も売りたいし求職活動にもなりそうならそのほうがいいかもね。シンプルな読み物ADV作る以外の用途では、プログラマはどうせ必要なんだから、そっちの実作業でお金取ればいい気もするのだ。

posted by NTak_Indies at 19:33| Comment(0) | TrackBack(0) | 日記