Unity:Wheel Colliderで車を組み立ててみる

UnityのWheel Colliderコンポーネントを使って車を組み立ててみる実験をしました。公式のCar Tutorialの車は動きが不自然で、実際、スクリプトを見ると妙なことをしているように見えたので(笑)自分で中身を把握できるものを作っておこうという感じで。まだToDoをたくさん残したまま間が開いてしまっていて、ちょっと投げっぱなしなんですが……。

Wheel Colliderは、タイヤのスリップに対する摩擦力と、サスペンションをシミュレートしてくれます。なら、車体に4つタイヤをつけてWheel Colliderくっつければとりあえず完成? と思ってしまうのですが、それだけでは駄目で、旋回すると遠心力でタイヤが浮いてすぐ横転してしまいます。重心をいじったり、ダウンフォースを与えてみたりとしばらく悩んだのですが、車体のロールを抑えるためにスタビライザーを組み込むのがポイントのようです。車に必要不可欠なパーツだったんですね。こうしたことを体験・実感できるのは、物理エンジンに触れる面白さのひとつだと思います。まあ、重要なヒントをもらったところでやっぱり調整は難しいんですけど。

ちなみにいろいろ調べているうちに知ったのですが、本格的な自動車のシミュレーションのアセットがあったりします。CPUカーのAIのアセットもあるようです。

Unityは、せっかく頑張っても「それアセットでできるよ」となって不貞寝してしまうようなことが結構……。

バックミラーの左右反転描画はこんな感じで投影行列とポリゴンを反転してます。

using UnityEngine;

public class MirrorCamera : MonoBehaviour
{
	void Start()
	{
		camera.projectionMatrix *= Matrix4x4.Scale(new Vector3(-1, 1, 1));
	}

	void OnPreRender()
	{
		GL.SetRevertBackfacing(true);
	}

	void OnPostRender()
	{
		GL.SetRevertBackfacing(false);
	}
}

コースの生成にはEasyRoads3Dを使用しています。Terrain上に引いたスプラインパスから道路や縁石、ガードレールなどのメッシュを生成し、Terrainをそれに合うようにならしてくれます。便利ですが、UIなどやや癖のあるアセットです。

道路とTerrainがZファイティングを起こすのを回避するため、EasyRoads3D付属の道路描画用のシェーダにはOffsetの設定が入っています。が、調整が難しいのでオフにして、手っ取り早く道路の高さを7.5cmほど上げて対処しています。そのため、段差で車体が跳ねてしまってたり……。

まだいろいろと課題が多そうですが、Unityのおかげでこういったことをわりと手軽に試せるようになったのは嬉しいですね。

2012年5月16日

CSS3でゲームっぽいメニューを作ってみる

UnityのNGUIというGUIツールキットのアセットがおすすめだそうなので試していたのですが、その中のかっこいいサンプルのひとつを見て、CSS 3D TransformsとCSS Transitionsで同じようなことがやれるのではと思ったので真似してみました(思いっきり脱線……)。iPadでも動きます。IEとOperaでは動作しません。

HTMLでゲームのUIを作るのは流行りっぽいんでしょうか。ブラウザをゲームのUI用に組み込んでいる話など聞きますし、UnityでもHTMLでUIを作ったとか、WebViewのプラグインが公開されるとか。十分にパフォーマンスが出るようなら便利そうです。

HTML5のブラウザゲームでも、例えばメッセージウィンドウなどは頑張ってCanvasで描画するよりもDOMエレメントをオーバーレイするほうが適材適所かもしれません。jQueryのプラグインなども利用できると思いますし。要は通常のウェブページを作るノリでUIが作れるわけですからね。

ブラウザだと互換性の問題が大変ですけど。こんなシンプルなものでも片っ端からPCや端末を立ち上げて確認してまわらないといけなくて(Flashならまず大丈夫なのに、なんてつい思ってしまいます)。特にAndroidは個人で検証するのは不可能に近いような……。

とりあえずベンダープリフィックスだけでもなんとかして欲しいです(笑)。

2012年4月17日

Dartの演算子オーバーロードを使ってみる

たまにはブログも更新しないと、ということで。以前Flashで作ったものをDart+HTML5 Canvasに移植したものです。ドラッグでポイントを動かせます(Operaで動かないのは……なんででしょう?)。リンク先にソースコードも置いてあります。

これはもともと、ActionScriptに演算子オーバーロードがなく、ベクトルの計算などが書きづらいのをどうしようかと試行錯誤したものだったんですが、例えばpositionとvelocityがVector2クラスのインスタンスだとして、

position = add(position, mul(velocity, deltaTime));

とでもするしかないかなという感じでした(詳しくは省きますが、実際にはこれじゃダメでしょう)。DartならVector2クラスにoperatorを定義すれば、

position += velocity * deltaTime;

のように直感的に書けます。

演算子オーバーロードというと、そんなもの要らないよと言う人も多いのですが、ベクトルや行列の計算にはあるととても便利なのです。ゲームプログラム(とりわけ3Dの)でC++が使われる理由のひとつとして、演算子オーバーロードで幾何学計算が素直に書けて、しかもコンパイラの最適化で十分に速いアセンブリコードが出力されるというのが大きいと思います。UnityのJavaScriptも、ベクトル等の計算が普通に書けるよう独自に拡張されています。

そんなわけで、Dartに演算子オーバーロードが入ってきたのは嬉しいです。……が、上の例がfrogcでJavaScriptにどう変換されるか見てみると……いちいち型チェックしてるんですか、これ。オーバーヘッドがかなり大きそうで不安w DartネイティブのVMに期待って感じでしょうか。

position = $add$(position, ($mul$(velocity, deltaTime)));

...

function $add$complex$(x, y) {
  if (typeof(x) == 'number') {
    $throw(new IllegalArgumentException(y));
  } else if (typeof(x) == 'string') {
    var str = (y == null) ? 'null' : y.toString();
    if (typeof(str) != 'string') {
      throw new Error("calling toString() on right hand operand of operator " +
      "+ did not return a String");
    }
    return x + str;
  } else if (typeof(x) == 'object') {
    return x.$add(y);
  } else {
    $throw(new NoSuchMethodException(x, "operator +", [y]));
  }
}

function $add$(x, y) {
  if (typeof(x) == 'number' && typeof(y) == 'number') return x + y;
  return $add$complex$(x, y);
}

...

ついでに、演算子オーバーロードは必要なんだ、という他の方の証言を。

JavaScriptになかなかつかない理由。いずれはなんとかなりそう?

余談ですが、DartといえばHello, WorldをJavaScriptに変換したら17000行になったというのが話題になりましたけど、今はだいぶ小さくなってます。このサンプルの出力(CanvasTest.dart.js)が150KBくらいです。Closure Compilerを通すと55KBくらいになるんですが、動かなくなるので、ちょっと調べないといけなさそうです。

(追記)ちなみにCoffeeScriptでも演算子オーバーロードの要望が何度も挙がって都度却下されているようなのですが、どうも、動的型言語からJavaScriptへのトランスレートでは非効率な変換結果にならざるを得ないようです。a + bという式があったときに、aとbの型が実行時まで決まらないので、関数の呼び出しに変換するべきかどうか分からないと……。

C#からJavaScriptに変換するJSILRaytracer Demoを見ると、演算子オーバーロードが素直に変換できているので気になります。ただ、こちらは出力が結構大きくなってしまうようですが。

2012年4月2日

Blenderの導入ガイドを書いてみた

Blender 2.60が出ましたね。最近更新ペースが速いです。12月のバージョン2.61では新しいレンダリングエンジンも入るとか。

で、つい勢いでBlender基礎最速マスターというものを書いてみました。タイトルは一時期人気になったプログラミング言語の基礎文法最速マスターシリーズにあやかっています。

Blenderはフルスペックのフリーの3DCGソフトウェアです。Unityとの連携で用いられることも増えていると思うのですが、癖がとても強いことでも知られています。できるだけ短時間でハマりポイントのうち大きなものをカバーできるようにしてみたつもりなんですが、どうでしょうねー。

ブログではなく通常のページにしたのは、また結構長文になってしまったのと、最近ウェブで検索したときに古い情報が出てくることが多い気がするので(数ヶ月前に書いたAIRのエントリももう時代遅れになってしまいましたし……)、固定ページとしてメンテナンスしたほうがいいんじゃないかと。

いざ久しぶりにページを作るとなると、URLを考えるのに困ったりするんですけどね。思い切ってunityというディレクトリを作ったので、そんな感じのものを上げていければいいなと思ってます。

近況としてはわりとUnity漬けですが、Flash 11も気になるところです。

2011年10月22日

Unityで1週間でミニゲームを作ってみた

最近なにかと話題のゲームエンジンUnity。ずっと前から気になっていてちょくちょくいじってはいたんですが、実際にゲームを作ってみたことはありませんでした。そんなところにIGDA日本のUnityのセミナーがありまして、面白そうな内容でぜひ行こうと思ったんですが、Unityをろくに触らないまま遠路出かけるのはもったいないということで、急遽ゲームを1本でっちあげてみました。

ゲームはこちらです。要求スペックはそこそこ高めです。

ちなみにセミナーの内容については「強火で進め」さんのブログにまとめられています。

以下、メイキング的なメモ書きです。

今回、時間がなかったこともあって、「リソースは自作しない」というのを絶対方針にしました。UnityにはAsset Storeという公式の素材マーケットがあるので、主にそこからフリーのものをいろいろ見つくろってきています。背景やトゲ付き鉄球など、全部既製の素材です。

また、プレイヤーキャラクターはMixamoを利用しました。有料ですが、3Dの人体モデルを作成したり、自作のモデルをアップロードしてモーションをつけたりできるサービスです。今回は、Mixamo本家で3Dモデルを作成して$10で購入し、Unityのプラグイン(Mixamo Animation Store)から歩きモーションと立ちモーションをそれぞれ$10で購入しました。しめて$30です。モデリングもモーション付けも自分でやるとものすごく大変な作業ですから、とりあえずこうして解決してしまえるのはとてもありがたいです。

ゲームデザインについてですが、作る直前にUnity上でラグドールの実験をしてまして、ラグドールが吹っ飛ぶのは面白いよねということで(ゲームのバグ動画などでよくありますよね)いろいろ物を投げ込んでぶつけて吹っ飛ばしてやろうと。物理エンジンも活用できるし、見栄えがするのでいいかなと思いました。

吹き飛ぶときの爆発はDetonator Explosion Frameworkを使用しています。Prefabをスクリプト1行で生成するだけで派手な爆発をしてくれるアセットです。ゲームの内容的にはなぜ爆発するんだって感じですが(笑)、一度使ってみたかったので。まあ、特撮などでも意味もなく爆発しますし。このキャラがそういう体質なんでしょう、きっと。

避けゲーということで安直にAvoiderとタイトル決定。たぶん主人公の名前か何かでしょう。タイトル画面は、Adobe Fireworksで適当にプリセットのスタイルを適用して字詰めしてロゴを作成、プレイヤーキャラを配置してライトを当ててできあがり。ちょっとでも動きがないと寂しいので、トゥイーンライブラリのiTweenを使って、ライトのフェードインとロゴの明滅をさせています。ちなみにこのトゥイーンライブラリというのはFlashの世界で生まれて発展してきたもので、簡単に言うと「動き」をライブラリ化したものです。コード1行でオブジェクトをアニメーションさせたりできます。UnityにもFlashのタイムラインのようなアニメーション機能があるのですが、Flash同様、トゥイーンライブラリのほうが楽に動きをつけられる場面が往々にしてあります。iTweenのサイトのExamplesに印象的なデモがたくさんあります。

ただ避けて生き延びるだけではゲームとして単純すぎると思ったので、宝石を取るとスコアが加算されるようにしました。ゲームはプレイヤーに2つ以上のことを同時にさせるといいそうです(参考:社長が訊く『New スーパーマリオブラザーズ Wii』)。というか、Asset StoreにGem Shaderというシェーダがあって、綺麗な宝石モデルも入っていたので使ってみたというのが本当のところで、順序が逆かもしれません。ちなみにシェーダの中身をまったく見てません。ブラックボックスのまま使って(使えて)しまっています。

宝石を取ったときにエフェクトがないと取った感が出ないのでどうしようかと思ったんですが、標準アセットのParticlesパッケージの中にあったFireworksをもうこれでいいやとそのまま使用。あとは、せっかくなのでコンボボーナスをつけたり、宝石を2種類にしてスコアを変えたりしてよりゲームっぽくしてみました。なお、時間が経つと宝石が小さくなって消えるのもiTweenを使ってます。

難易度調整、実はこれが一番時間がかかったかもしれないんですが、NORMALモードとHARDモードを用意するという逃げに走りました。あとカメラアングルは最初もっと低かったんですが、フィールドの上のほうがオブジェクトに隠れて見づらくなり、下のほうばかりをうろうろするプレイになってしまって、あまりに不自然だったので、ほとんどトップビューにしてしまいました。せっかくのキャラクターがよく見えなくなってしまうので躊躇したんですが仕方なしです。タイトル画面のアップでカバーする感じですかね(笑)。それと、プレイヤーキャラの当たり判定は、胴体より下だけにしてあります。

BGMは、一応DTMerなので本来なら自作するべきところなんですが、CubaseのLoopMashのプリセットをちょっといじって書き出してシーンに配置して終わり。宝石を取った効果音もCubase付属音源から適当な音色を探してきて使用。オブジェクトが跳ね返る音は効果音素材CDからです。

と、こんな感じで作ったんですが、ゲーム内容的にも制作工程的にも相当横着してますね。とりあえず見ていただいた方々に面白いと言っていただけたので(ありがとうございます!)いいのかな?と思います。既存のアセットを使いまくってるのはバレバレでしたけど(笑)。

*

さて、こうして短期間で1本でっちあげてみて、Unityのことが以前よりもずっとよくわかったというか、正直、過小評価してたような気がしてきました。すごいゲームエンジンだとは認識していたんですが、ゲームエンジン本体よりも、周辺の文化圏こそが真価だったんじゃないかと。今回、他人のアセットの力を素直に借りようと最初に決断していたとはいえ、素材を探してぽんぽん放りこんで、ちょこちょことスクリプトを書き足すだけで、あっという間にそれっぽいものが組み上がっていくのは、いいんだろうか本当にって感じでした。ほとんどチートのような気もするんですが、実はこれが本来の使い方(のひとつ)なのかもしれません。セミナーの講演の中でもレゴブロック的という話があったように記憶しています。

実のところ、現状のAsset Storeはサーバがかなり重かったりして、お世辞にも使いやすいとは言えないのですが(公式フォーラムのこのスレッドで、Unityの中の人いわくなんとかするそうです)、そのあたりが解決されてアセットの数が増えれば、さらにとんでもないことになりそうな予感がします(なお、ゲームに使用可能な3D素材については他にもTurboSquidなどがあります)。

あと、スクリプトについても、まだ慣れていなくてAPIがあまり身についていないのですが、何か引っかかったらUnity Answersフォーラムで検索すればすぐ答えが出てきましたし、そもそも今回自分で書いたJavaScriptコードが全部で600行ほどしかありません。流暢に書けなくてもどうにでもなる量です。

このスピードとこのコード量で、1人で、仮にも物理エンジンが走り、人体モデルが動くような3Dゲームをでっちあげられるというのは、今までは考えられなかったことなんじゃないでしょうか。3Dゲームを作れるのはナムコとセガくらいみたいな時代もあったと思うんですが、すごいカジュアル化です。Unityが言うには「民主化」とのことですが、ある意味、言い訳ができなくなりつつあるようで、ちょっと怖いなと……まあ、一方で、リソース作りが大変なのは基本的に変わらないとも思うんですけどね。

こうした至れり尽くせりのゲームエンジンに乗っかれるかというのは、特にプログラミングをする人にとって心情的に難しいところもあると思うんですが、自分の場合はどうもメリットのほうが大きそうなので、本気で乗っかってみようかなと考えはじめてます。

とりあえず、もう1本くらい実験作を作ってみたいですね。もうちょっとシーンやスクリプト的に凝った何か。

2011年7月19日

トップページ
プロフィール

はてなブックマーク
wonderfl