Más contenido relacionado
La actualidad más candente (20)
Similar a ゴルフゲームでUnityの限界を突破する方法 (20)
ゴルフゲームでUnityの限界を突破する方法
- 2. 自己紹介
• 饒平名 秀成(のひな ひでなり)
– へなちょこエンジニア
– 入社4年目の新卒2年目(いわゆる新古品)
– 沖縄県宮古島出身
六本木でモバイルゲームつくったり Unity で遊んだりしてます。
絵描きになりそびれて今はエンジニアやってます。
実家のマンゴー畑の行く末が当面の悩み・・・
- 13. ゴルフパラダイス ( 仮 )
• ここがこだわりポイント!
– ボールを遠くへ飛ばす爽快感
– スマホでもハイエンドなグラフィック
← ちなみにこんなプレイ画面(仮)
- 28. なぜ Unity を選択したのか
• 主だった処理はエンジン側がだいたいや
てくれる。
• なので動くものを見せられるまでが早い
。
• 他社のものとくらべても比較的安価。
• コミュニティが活発で問題が起きても誰
かしらがそれを解決してくれている。
- 34. しかし、そう上手くはいかないも
ので
• Unity はだいたいなんでもやってくる
• けれど思わぬところに落とし穴が・・・
– シンプル設計が故に意外とかゆいところに手が届か
ない
– 品質向上のためにはそれなりの努力が必要
– コアの部分に手をつけたくてもコードが公開されて
いないから無理
– 多人数で開発した際のコンフリクトの多発問題
意外と予想外な問題に突き当たる。
プロトタイプを作ったあとの開発はそんな
に楽じゃない。
- 35. 特に問題を抱えたのが
• 物理演算
– Unity の Rigidbody はあくまでも剛体シミュレー
タオンリー
• 速度と重力の計算しか入っていない
• 空気抵抗などの計算があまり考慮されていないので、実際
のボールの軌道とは似つかない
– ボールに回転を加えても無回転で飛んだ状態と同じものとし
て計算される
– 回転が挙動に大きく影響を与えるものには向かない
– 処理がブラックボックス化されていることによる問
題
• 厳密な計算が難しい。
「このドライバーでこれくらいの力で打ったら 230 ヤード飛ぶ」
というようなパラメータの設定や推定が難しい。
- 39. 我々がやりたいこと
• 打撃に爽快感が欲しい
• 回転で浮き上がり、空気抵抗で失速しな
がら飛んでいく、現実のゴルフボールの
ような挙動を実現したい
– これは Unity の生の演算処理では不可能
← こういう軌道にしたい
http://yspz.blogspot.jp/2010/04/4.html
- 40. 実際にやったこと
• 物理演算部分は Unity のものを使わず
、自前で実装する
– ただし、あくまでもゲームなので、精度を
追求するわけではない
– 要件を満たす程度にある程度の物理的な挙
動を模擬する
– こだわるのは打撃時の爽快感
- 41. 前提
• 滞空時の動作に対する演算は、
– 速度( Velocity )
– 質量( Mass )
– 空気抵抗( Drag )
– 重力( Gravity )
くらいしか使われていない
ちなみに、 Drag や Mass の影響を出ないようにパラメータを調整し
て、 Unity の生の演算と、自前で処理をかけたものを比べるとだいたい同じ
結果になった。
rigidbody.velocity += Physics.gravity * Time.deltaTime;
• また、使われているものもそこまで
厳密ではない
- 53. 実際に使った計算
• 定数定義
– Fw : 重力
– Fd : 抗力
– Fl : 揚力
– U : 対空気速度( m/s )
– N : 回転速度( rps 。ゴルフ関係の資料は rpm なことが多いので注意)
– m : 質量
– g : 重加速度
– d : ボールの直径
– A : 前面投影面積
– ρ : 空気密度
– Kv : 空気動粘度
– Cd : 空気抵抗係数
– Re : レイノルド数
- 54. 実際に使った計算
入手した資料内の公式から
– Fw =m*g
– Fd = 1/2 * Cd * ρ * U^2 * A
– Fl = 1/8 * π^2 * ρ * d^3 * U * N
とすると、ボールにかかる力 F は
– F = Fw + Fd + Fl
各種パラメータを決めてやって、
上記の式に入れ込むとボールの移動速度が算出できる。
※ この資料で利用する公式は一部ゴルフボール
を完全に球体だった場合として簡易的に近似
していることに注意。
- 55. 実際に使った計算
• 定数の値の設定
– まず、簡単に決められるものから
m = 45.3 / 1000 ※1
d = 42.7 / 1000 ※1
g = -9.81 ※2
あたりの数値を入れる。
※1 これは各社のゴルフボールの規格によって変わるので適当
な ものをんでやる。
※2 g は実際には Vector3(0, -9.81f, 0)
とか Physics.gravity とか使ってや
れば良いよ。
- 58. 実際に使った計算
• Re が決まったので、 Cd の値が算出できる。
– ただし、この Re-Cd 関係は算出する式が存在しない(実験
データとの照合の必要がある)。
– 完全な球体として扱って良い場合は、適当に以下のような近
似式を使う。
Cd = 24/Re
* (1 + 0.152 * Re^(1/2) + 0.0151 * Re)
※ Re-Cd 関係はメーカー(というよりも各ゴル
フボールの規格)によって全然違う数値に
なる。
※ 特にメーカー等の指定がなければ、学術論
文やゴルフボールの特許資料などに乗って
いる実験値などから適当な値を抽出。
※ 実際には、収集したデータをもとに、上記の
近似式をあるゴルフボール用に改良(という
よりも操作)を加えたものを利用している。
- 60. 実際に使った計算
• 最後の3つのパラメータは実測ベース
– 基本的にはネット上に出回っている標準
データを利用する。
– ただし、特定のクラブの特定の条件での打
撃などで抜け漏れが発生する。
• なので、実際に現場に行ってデータを計測する
。
※ ちなみに、ここで計測したデータはけ
っこう重要で、なかなか出回らない
ショット失敗時のデータも取得できる。
- 65. できるようになったこと
• ボールの回転による空気抵抗まで加味するの
で、より自然なかたちでボールが 飛ばせるよ
うになった
• 事前にどの程度の力を加えればどの程度ボー
ルが飛ぶのか判断できるようになった
– ただし、⊿ t(deltaTime : 微小時間 ) 毎に次々の
タイムステップを計算していくような、時間領域の
差分を利用する方法では、実際に計算を回さないと
結果はわからない
– なので、飛ばしたい距離分打つにはど
の程度の力を加えれば良いのか裏で
計算 をして力の設定をしています
- 70. 今回お話したのは
• キャリー ( 飛来 ) 中の弾道シミュレーシ
ョン
• 実際は以下のものも自前で起こしていま
す
– バウンド時の跳ね返り方向の判定
– ラン ( 転がり ) 中の挙動シミュレーション
- 71. 参考にしたデータ
• テニスの力学
– http://goo.gl/m9kym
• ゴルフボールの弾道シミュレーション方法
– http://goo.gl/e8Usx
• ゴルフボールのディンプル数に対する飛翔特性と流れ
– http://goo.gl/0zPDu
• AERODYNAMICS OF A GOLF BALL WITH GROOVES
– http://goo.gl/JQGU5
• 地球の雨・タイタンの雨
– http://goo.gl/ypiYw
• 土木工学ハンドブック
– http://goo.gl/HT4KT
• 転がりの科学
– http://goo.gl/PQtLv
いろいろ資料はあるけど、だいたいこれだけ読めばお k !
- 74. データのフォーマット問題
• ロードできるデータが固定されている
– Resources.Load 、 AssetBundle で使
用可能なフォーマットが固定
• パラメータ設定とかに CSV とか使いたいよね…
• なので、独自のローダを開発!
– Resources.Load で読めない例外的なデータはこち
らからローディング
- 75. ローカルのセーブデータ
• Unity 内臓の PlayerPrefs クラスなんかだと
、直接データを覗けば簡単に構造が読めてし
まう
– XML や JSON も同様
• C# の BinaryFormatter でシリアライズす
るパターンも、直接抜き出してデコードした
ら一発で解析可能
– ファイルの冒頭に「 Assembly-CSharp 」という
記述があるため、すぐにデコード方法は推定可能
– そもそも、 BinaryFormatter は iOS で利用でき
ない
※ 余談として、データの保管には
EZ Saver といアセットがある
- 76. ローカルのセーブデータ
• 解決策
– セーブデータをハッシュ化したものを文字
列変換して保存する
• こんな感じ
– EXP:100;LEVEL:3;CURRENT_STAGE:5;
– 変換した文字列を公開鍵暗号を利用してさ
らに 16 進数の文字列郡に変換
• 鍵はサーバ側で定期的に更新して
おけば安全
- 80. 速度チューニング
• Raycast 飛ばしすぎ
– Raycast は処理が重たい
– NGUI などの GUI ツールは Raycast でタップ判定をしてい
る
• ここはなるべくひとつのカメラにまとめる
• GUI/ 演出でカメラがいっぱいある
– 実は Unity は画面に描画をかけていなくても、場にカメラが
存在するだけで計算が入る
• 利用していないカメラは小まめに deactive に
• データのロードで固まっちゃう
– エフェクトのロードなど、一度にたくさんのデータや、重た
いデータのロードをかけると一瞬固まってしまう
• 確実に利用されるとわかっているデータは事前ロード
– シーンを開始した最初のフレームで読み込んでいる
– 若干、機動が遅くなるがあとの処理落ちは回避できる
- 81. GUI と日本語
• DrawCall 削減のために GUI は基本的に NGUI と
iTween
– 一部例外的なアニメーションは iTween を拡張して独自実装
• 日本語化
– Unity では日本語のダイナミックフォントがサポートされて
いない
• Bitmap Font Generator ないしは Glyph Designer を利用
する
– TTF 形式のフォントをビットマップ画像に変換し、テクスチャ化し
たものを文字データと関連付ける
• これだけだと、一枚のテクスチャにすべての
文字データが入っていけないという仕様上、
利用できない文字が発生してしまうので、ユ
ーザが「日本語で」自由入力する部分は Web
View の機能を利用する
※ Unity4 では日本語が標準サポートのようです。
- 82. GUI と日本語
• GUI の今後
– オートデスクの Scaleform が便利そう!
• Flash ( AS2/AS3 )で作成したコンテンツを
利用するためのソリューション
• もともと Web アプリを作っていた会社のため、
Flash の知識のある人材がデザイナに多いので
、こちらに移行する(かも)
– 試しに別案件の Flash ゲームを Unity に移植したと
ころ簡単に動作できた!
– Unity のバイナリではなく、 SWF のデータ
で扱うため、シーンの編集中に他人の書い
た GUI を壊しちゃった、みたいなことも少な
くなりそう
- 84. 分析ツール
• ユーザの行動分析はどうするか
– Flurry を導入予定
• こちらは未だ実装に入れていないので、あくま
で「予定」として
※ 別の勉強会で話を伺った某社は Google
Analytics を利用しているとのことでした
- 85. 仕様でのバグバグ
• Application.LoadLevelAdditive() につい
て
– LoadLevelAdditiveAsync にしなかった際に
「シーンを読むまで呼び出し元の処理を止める」も
のと勘違い。
• 実際には「シーンのロードが終わるまで次のフレームに行
かない」
– ちなみに、 Application.LoadLevelAdditive() も
Application.LoadLevelAdditiveAsync() も、
内部的には Application.LoadLevelAsync()
を利用してシーンを読み込んでいる模様
基本的 にシーンを読む関数はすべて
最終的にこちらを参照するようになっ
ている
- 91. まとめ
• Unity はプロトタイプ開発には便利
• だけど、本当に凝ったことをしようと思
うとひと手間加える必要がある場合があ
る
• 結局のところ、コンテンツを作りこんで
いく苦労は Unity でも変わらない
• ただし、難しいことは調べれば既にあっ
たりする(特にアルゴリズムと数式系)
– 意外と学術論文とか使えるんです!