UE4でパーセント表記
戦績などのスコアを表示するリザルト画面や、武器やキャラのステータス表示で、「命中率」や「回避率」など「○○率」を表記することがよくあります。
この「○○率」を表示してやんよ~というわけで気軽にやってみたのですが、なかなかうまくいきませんでした。ははは。
例えば、命中率の計算。必要な情報は 『撃った弾数』と『当たった数』です。
基本的に『当たった数』を『撃った弾数』で割ればよいだけです。
100発100中なら100%と書けばいいのですが、300発100中ならどうなるでしょう。
100 ÷ 300 で 0.33333333333333333333333333・・・・
このように割り切れない場合があります。これを、33.33% と書きたいわけですよ。で、どうするか? 昔JavaScriptで覚えた方法を試します。
小数点以下2桁にしたい場合。
100 + 2桁のゼロ で 10000 まずは この 10000 を掛けてやります。
ゼロが4つで、小数点が4つ移動します。上の場合 5898.7654
掛けた値を四捨五入します。四捨五入した時点で小数点以下は消えるので、整数になります。この時点で、4桁の整数になっています。 上の場合 5899
それをさらに 100 で割ります。小数点が右端から2つ移動します。
PrintStringノードで表示してみます。
58.99 が表示されればバッチリです。
!
な、なんじゃぁこりゃぁ。2はどこから?
ネットで調べてみると、どうもイロイロ事情があって仕方のないものらしい。
コンピュータは基本 0 と 1 の2進数で動いていて、この2進数で小数点を表すことが苦手なようで、上のような微妙な誤差が生まれるとのこと。お金の計算でこの誤差はヤバいのでさすがにちゃんと対策されているそうです。なるほど小数点を扱うのは結構難しいもんですね。ふふふ。
いやいや。表示しなきゃいけないのですよ。
で、思いついたのが、四捨五入した時の Int型の値を、String型(文字列)にして分割してしまう方法。
整数同士の割り算は小数点以下を切り捨ててくれます。 上の場合 5899 ÷ 100 で 58。
うまくいきました。
ただこの方法だと、 必ず小数以下の2桁分がくっつけられるので、割り切れたとしても最後に0が付きます。
0.5 の場合、0.5 × 10000 = 5000 になるので、 50.00% と表示することになります。
なんか面倒な感じがして釈然としないので、便利そうなノードが用意されてたりしないかな、ゲームエンジンなんだし・・・と思いつつ探してみたらありました。
AsPercent ノード。
Epicありがとう!
Float型の値をパーセント表記に、しかもテキストで返してくれるというすぐれもの。
Text型ということは、UMGのTextBlock でサクッとと表示できて便利です。結果は、
おお!カンペキ! もっと早くに出会っていれば・・・(涙
右端の桁に 0 もつかないというシンプルさ。
ちなみに、小数点以下を固定の桁で四捨五入するのを「丸める」といいます。
AsPercent ノードの設定で好きな桁で丸めることができます。
Rounding Mode は丸める方法です。
ということで無事解決しました。
プログラマにテキストで頂戴って言えば、きっといい感じの関数を書いてくれそうですが、やっぱり表示する部分はUIデザイナーでも頑張ってみたいところです。
ではでは
今回はこの辺で
A と B を交互に切り替える処理でハマった話
TVのリモコンを握っている状況をイメージしてください。
TVが点いていない状態で電源ボタンを押すと起動して、点いている状態で押すと待機モードになります。
どちらの操作も同じボタンを押すことで切り替わります。
このように、A と B の2つの状態があって、一つの関数を呼ぶだけでスイッチングできないかなと思って試してみました。
実行するたびに、2つの処理を交互に切り替えたいので、引数で切り替えるのは無しです。
ようするに関数を単純に呼び出す(Call)だけでスイッチングしたいのです。
呼び出す側は「関数の中身なんか知ったこっちゃねぇ。」という状況が理想。
さらにシンプルなノードでできると尚良し。でやってみたのがこれ。
XOR ノード は 「排他的論理和」というやつで、同じものが来たら反転するというひねくれものです。違うもの同士は足します。↑の場合チェックボックスにチェックが付いている状態なので、
結果をすぐに変数にセットしてるので、内容が反転したことになります。
できれば変数を使わない方法でシンプルにできないかと思ってやってみたのがこれ。
結果はというと・・・
ここでようやくハマった話。
この MultiGate ノードを使ったつなぎ方は一度経験していて、当時はうまくいってました。で今回は「なんで?」となったのです。
結論を言ってしまうと、MultiGateノードは関数内に置くときは取り扱い注意 です。
単に「ランダムな結果を返せ」だったら is Random にチェックを付ければ問題ないです。今回のように上から実行ピン(Out 0 → Out 1 → Out 2 ・・・)を順番に流す場合はうまく働いてくれないことが分かりました。
関数の外に置いてみるとうまく働いてくれます。
Epicの公式ドキュメントにそれらしい記述が見つけられなかったので、当たり前の仕様なのか、バグなのかはプログラマじゃないのでなんとも言えないですが、ちょっと謎です。
もっとシンプルに切り替えるノードを思い出しました。FlipFlop ノードです。
「MultiGateはそういう仕様なんだ、でもFlipFlopなら状況を打開できるかも・・・」
と淡い期待を抱きつつ・・・
こちらも関数内に置いて使うと、Aのピンしか流れません。
外に出してみるとうまく動きます。
結局、外部から呼び出してスイッチングしたかったので、カスタムイベントにつなぐことで解決しました。
これでバッチリです。
ちなみにマクロの中で使う分には問題なく動作します。
ですが、そのマクロを関数の中に置くと、切り替わらないという結果になります。
あくまでも推測ですが、
切り替えるには、状態を保持しておく値が必要で、関数内からはその値が参照できなくなるんじゃないかと思ってみたり。
ではでは
今回はこの辺で。
ステキなノーディングライフを!
5分で作る マテリアルを使わないゲージ
超簡単お手軽ゲージを作ってみます。マテリアルは使いません。
Widgetブループリントを一つ用意します。
キャンバスに配置するパーツは3つ。
ゲージ用のキャンバスとゲージの下敷きは同じ大きさにします。下敷きは暗めの色にしておきます。
ゲージ本体の「Image」をキャンバスの子供にしたら、設定をサクッと変更します。
まずはAnchors(アンカー)を右下のやつに変えたら、
すぐ下にあるOffset関連の値をすべて0.0にします。
カラーを適当な色にしたら、
最後にキャンバスパネルの isVariable のチェックを入れて完成です。
編集モードをグラフに切り替えて、MyBlueprint のタブから、Function(関数)をひとつ追加します。
中身は以下。
コンパイルしてエラーがなければ保存して完成です。
レベルから確認してみます。
レベルブループリントを編集します。
再生してみると、
スペースキーを押すたびに長さが変化します。
完成です。
実際に時計見ながら作ってみたのですが、5分かからなかったです。
見た目には安いですが、このスピード感は大事です。
ゲージ一本でゲーム性やバランスが大きく変わるのはよくある話です。
ではでは
ステキなゲージライフを!
最近ハマったつなぎ方
ちょっとネタが無くなってきたのもあって更新ペースが落ちてます。
なので自分のウッカリでもさらしてみようかなと。
それは思ったような値にならず、原因も分からず、しばらく首をひねっていたつなぎ方です。
まずUMGでパーツを置いて、Widgetブループリントからいい感じにサイズを計算して調整しようとしました。
下図は 160x256 サイズの”Image”です。
これを、下のようにつなぎました。
計算した値を別のところで使いたかったので変数に保存しています。
ここで察しのいい方は気づかれていると思います。
Imageパーツのサイズをゲットして、タテ方向だけ1/16 にしてサイズを変更しています。
果たして、変数 Value の値はどうなっているでしょうか?
再生すると、パーツの見た目には うまくいっているように見えます。
でも、
答えは、 Value = 1.0 です。
え?
だって 256を16で割ったら16でしょ? なんで???
実際には 256 ÷ 16 = 16 したあとで、さらに 16 ÷ 16 = 1 となっているからです。
なんと割り算が2回計算されているのです。
SetSizeノードに割り算の結果が渡されたあとで、次は変数に値を渡すためにもう一度Imageパーツのサイズを取得して(このとき既に16になっている)16で割っています。
見た目に、割り算ノードのあたりで計算が済んでいるように見えるのと、同じピンから取り出してるので、同じ値が出てくると思ってしまったのが原因でした。
正しくは以下。
変数に値を入れない場合でも、値を確認しようとしてPrintStringノードをつなぐと・・・
1.0 という数値が表示されます。
PrintStringノードが値を表示しようとして、2回目の計算を行ってしまうためです。
では以下の場合はどうでしょう。
無事 16.0 という数値が表示されます。Imageパーツはというと問題なく 1.0 にならずに表示されています。
おそらくこれも2回計算していますが、PrintStringノードは、SetSizeノードのように結果を反映しないので、問題が起こらないのです。
この辺りのロジックが理解できるまでしばらくの間、首をかしげっぱなしでした。
以前に 乱数を発生させるノードでも同じようにハマったのを思い出しました。
例えば下のようにつないだ場合、
画面には、2つの異なる数値が表示されます。
以後気をつけます。
ではでは
ステキなノーディングライフを!
スタッフロールをつくる 《完結編》
鶏肉は柔らかいのより噛みごたえのある方が好きです。
で前回の続き。
名前を表示するための器が用意できたところで、次に必要なのは中身です。
スタッフロールには関わった多くの人々の名前が載るので結構な行数になることが多く、それをブループリントの中で管理するのはさすがにちょっと躊躇われます。また、スタッフロール用の情報を集めて整理するのはExcelやテキスト系エディタの方が向いています。
というわけで今回CSV形式のデータを扱います。詳しくはヒストリアさんとこのブログにあります。
[UE4] CSVデータを扱う方法 DataTable編 | historia Inc - 株式会社ヒストリア
CSVは『カンマせぱれいてっどバリュー』の頭文字を合わせた用語で、簡単に言うと「カンマで区切った値」ということになります。Excelだと簡単に書き出せるのですが、Excelを持ってないのでテキストエディタで作りました。
いくつかのデータをカンマで区切るのですが、今回4つのデータで構成します。
Index番号 , 表示タイプ , 名称(文字列) , 次の行までの待機時間(秒)
用意したWidgetは3タイプ。表示タイプを『グループ』『パート名』『人名』を0~2の数値で扱うことにします。で、できたのが以下
,NameType,NameString,NextInterval
0,0,STAFF,2.0
1,1,ROSE,1.0
2,2,Abigaile,1.0
3,2,Acropolis Romantica,1.0
4,2,<>Alphonse Dauder<>Anthony Meilland,1.0
5,2,<>Bienvenue<>Benjamin Britten,1.0
6,2,<>Cassandra<>Cioccofiore,1.0
7,2,<>Dorothy Perkins<>Gloria Mundi,3.0
8,1,DAHLIA,1.0
9,2,Anto Norma,1.0
10,2,<><><>Azumabeni<>Ben Houston<>Blookside Snowball,1.0
11,2,<><><>Devon Liam<>Freedom Fighter<>Gregory Stephenl,1.0
12,2,<><><>Happy Face<>Hoshitsukiyo<>Lavender Giantsl,3.0
13,1,TULIP,1.0
14,2,<>Dalvey Snow<>Cardinal Mindszenty,1.0
15,2,<>Finola<>Flaming Prissima ,1.0
16,2,<>Honoonomai<>Lambada,1.0
17,2,<>Maywonder<>Murasaki suisho,1.5
18,2,Page Polka,1.5
19,2,Ruby Prince,3.0
プレーンテキストなので Tab文字 を入れれば見やすくなりますが、文字として扱われてしまうのでCSVとして書き出す直前に置換して消すといいです。
文中の <> は分割するためのデリミタ用の文字です。
この内容で、拡張子 .csv を付けて保存するとUE4でインポートできます。
インポートする前に用意するアセットがあります。Structureです。
ストラクチャーを作ったら適当に名前を付けて編集を開始します。編集と言っても変数を登録しておくだけのものです。
表示タイプ(Int型) , 名称(String型) , 次までの待機時間(Float型)なので3つ。
4つのデータを仕込んだはずですが、今回 Index番号については特殊な扱いをするので変数にはしません。
追加したら保存して閉じます。
いよいよインポートします。作ったCSVファイルをコンテンツブラウザにドロップすると下のような小さなダイアログが出てくるので、先に作っておいたStructureをプルダウンリストからアセット名で選択します。
OKするとDataTableアセットのエディタが開きます。
問題なければ左上のFile メニューから 保存 して閉じます。
このエディタからも内容の編集が可能ですが、スタッフロールについてはReimportをオススメします。名前の収集がメールベースというケースがほとんどで、最後までExcel等で管理した方が修正も楽ちんでお手軽です。
Reimportは、コンテンツブラウザのアセットアイコンの上で右クリックすると簡単にできます。
器と中身が揃ったので、表示する処理を作っていきます。
ブループリントアクターを使ってWidgetを表示します。
まずは、変数を2つ作って、Event Begin Play のところででセットします。
中央の見慣れない色の変数は、 UserWidget型の変数です。作る際にClass を選択するのがポイントです。
Make Array ノードをつないで、用意してある3タイプのWidgetアセットをセットします。
次に、メインとなるカスタムイベントを作ってつないでいきます。
まず最初に、DataTableアセットを取り込みます。
DataTableを取り込むノードは2つ用意されているようで、getdata で検索します。
Get Data Table Row ノードは Indexの値をName型に変換して、RowNameピンにつなぐとヒットすれば、その内容を取り出すことができるノードです。青いピンにまとめられているので、Breakeノードで分解すると変数ごとに振り分けられたピンが出てきます。それを使ってどんどんつないでいきます。
図の Wd Credit Text (実際は wd_CreditText)という名前の変数は Create Widgetノードの 右にあるReturnValueピンから、一度 Promote to Variable(変数化)してから配列化したものです。今回インターフェイスを使ったしくみが活かされている部分がここです。
左の Create Widget ノードにはまだどのWidgetが入るか確定していません。確定していない証拠に ReturnValueピンから作った Wd Credit Text の型は User Widget型のままです。普通ならClassの部分にセットしたWidgetアセットの型になるはずです。そしてその型が確定しているからこそ中の関数やイベントを呼び出せるのです。ところが確定していないのに中に作ったイベント StartMove を呼び出すことができています。これがインターフェイスという仕組みなのです。StartMove ノードの右上に 封筒のアイコンがついてます。ノードを取り出す際に ”start” で検索すると取りだすことができます。
インターフェイスを持っている相手なら、誰であるか特定できていなくても、そのインターフェイス経由で関数やイベントを呼び出すことができるのです。
おかげでノードのつながりがシンプルになります。
では続きを。
各Widget仕込んだイベントディスパッチャーにバインドしています。これは「移動が終わったら連絡ちょうだいね」という部分で、連絡を受け取ったあとの処理を下の赤いラインの先で行っています。
バインドもインターフェイスの仕組みでできれば、スイッチノードで分けたりキャストしなくて済んだのですが、残念ながら無理でした。Set Timer by Event ノードは指定した時間がきたらEventピンにつないだイベントを呼び出すノードです。で、どこにつなぐかというと、先頭です。
これで、Forloop などのノードを使わずに、イベントがイベントの終わりで自分自身を呼び出すカタチになります。このイベントが呼ばれると
- データテーブルから1行分のデータ取り出す
- 指定のあった名前表示用のWidgetを生成して配列に積む
- Viewportに追加してStartMoveイベントを呼ぶ。このとき名前のテキストを渡す。
- 移動完了の連絡を受け取るためにバインド
- データテーブルの指定通りにタイマーをセット
- Index変数を一つすすめておく
という流れで処理されます。
で、移動完了の連絡を受けたら、もうそのWidgetは用済みなので、メモリ節約のために削除してやります。
先にViewportの方から削除します。スタッフロールは下から順番に出てきて順番に消えていくものなので、配列に積んだ一番古いやつ=先頭から消すことで新陳代謝できます。
ほぼ完成なのですが、このイベントを呼び出さないとイベントは動きません。
そこで Event Begin Play の最後につないでやります。
ところで、このループはいつ抜け出るのか?という心配をされている方、ご安心ください。Get Data Table Row ノードが解決してくれます。
Index という変数が肝だったのです。Name型にキャストして検索。見つかれば Row Found、見つからなければRow Not Found に流れます。これで、データテーブルから該当するナンバーが無くなったらこのイベントのループは終了します。
今回も長い道のりでした。
ようやくこの作業が報われる瞬間がやってきました。
では表示してみましょう。
空っぽのレベルを開いて、作ったこのブループリントをエディタのViewportにドロップします。場所は適当で構いません。そのままPLAYボタン押せばOK。
・・・
なんかしみじみ。
自分の名前を入れてみるとより感動するかもしれません。
内容が変わったときは、リストを編集して再インポートすればすぐに確認できます。
新しいWidgetを追加する場合は、まず↓
そして
あとは、CSVデータの方に追加した表示タイプを入れればOK。
ロゴもWidgetを複製して改造すれば同じ方法でどんどん追加できます。
以上です
ではでは、ステキなスタッフロールライフを!
スタッフロールをつくる 《Widget準備編》
画面の下から出てきて上に消えていくだけの、どシンプルなスタッフロールを作ってみました。
今回用意するアセットは以下の6種類8個。
右のWidgetブループリント3つはほとんど同じ内容。
スタッフロールは、ただ名前が並んでるだけではなく、組織やグループ、セクション、パートなどの名称、協力会社さんのロゴ、俳優さんや声優さんなどは役名と対で表示したりと、結構表記のバリエーションを用意する必要があります。
今回は『グループ名』、『パート名』、『人名』の3種を作ります。
人名に関しては、1列~3列まで対応します。
まずは見た目の材料ということで、グループ名のWidgetから。
キャンバスの適当な場所にテキストブロックを一つだけ置きます。
文字サイズは 少し大き目にして他と差をつけるために色を付けます。
位置を調整する前に アンカー の設定を変更します。
決定するとキャンバスの表示が変わります。
次にSlotの中にある Anchors のパラメータを変更します。
SizeY以外を 0.0 にすると下のようになります。Position Y を動かすと移動できます。
最後に Is Variable にチェックを付けて、UMG編集完了です。
次に
Widgetブループリントを編集します。
スクロールに必要なFloat型の変数を 3つ用意します。
キャンバスに置いたTextBlockをグラフにドラッグ&ドロップしたら、Event Constructノードにつないでいきます。
UMGで配置したものをブループリントから触る場合、Slot as Canvas Slot ノードを利用します。上のグラフは、画面下から出現して画面上に消えるまでの移動量を求めて変数に入れています。とりあえずフルHDモニタ想定で以下のイメージになります。
今回選んだアンカーの設定にある PositionY は、0.0でスタートして最終位置は マイナスの値になります。そこで -1080 から サイズ(高さ)を引くことで、最終位置を求めることができます。720pだったら、 -720 から引いてやります。解像度に対して柔軟に対応する場合は、Get Viewport Size ノードがあるので、その値を利用するとさらに汎用性が上がります。
最終位置を求めるのにわざわざGet Sizeノードを使わなくても、動かしてみれば簡単に最終位置は判明します。これは、あとからサイズを調整する際、変数の値を変更しなくてもいいというのとマジックナンバーを使わなくていいというメリットがあるためです。気軽に感覚的にサイズを調整することができます。こういうちょっとした処理を仕込んでおくだけで調整の手数を減らすこともできるのでオススメです。
次に
移動が終了したことを伝えるためにイベントディスパッチャーを用意します。
追加ボタンをクリックして名前を付けるだけでOK。
とりあえず onMoveEndと名付けました。
移動させる部分を作っていきます。
Event Tick ノードにつないでいきます。
In Delta Time ピンからは フレーム毎に下図のような数値が流れてきます。
フレームというのは映画でいえばフィルムの1コマにあたります。
これは 60fpsの場合ですが 1秒を 60で割った値とほぼ同じで、直前のフレームからの経過時間を表しているそうです。若干のバラツキはありますが、ここに60 を掛けてやれば、1フレームあたり 約1という値になります。なので 変数Speedに60が入っていた場合、1フレームにつき1ピクセル進むことになります。120が入ると2ピクセルになるのでスピードが上がります。
1フレームに進む移動量をY座標に足して、限界を超えたかどうかチェックします。
越えていなければY座標をテキストブロックに反映して次のフレームへ。
越えたらイベントディスパッチャーを呼び出します。
イベントディスパッチャーは ドラッグ&ドロップしてCallを選択したものです。
一旦ここで編集を終了して、ブループリントインターフェイスを作ります。
適当に名前をつけて開いたら、右上に New Function_0 という関数があらかじめ置いてあるので名前を変更します。とりあえず StartMove と命名しました。
続けて、下のDetailsタブから、Inputs(引数)を2つ追加します。
これでブループリントインターフェイスは完成です。コンパイル→保存して閉じます。
さきほどのWidgetの編集を再開します。
編集モードをグラフにすると、エディタ上部にClassSettings というボタンがあるのでクリックしてDetailsタブの内容を切り替えます。
DetailsタブにInterfaceを登録する場所があるので、Addボタンをクリックしてさっき用意したブループリントインターフェイスをセットします。
追加できたら、グラフの何もな無いとこで右クリックして
ブループリントインターフェイス内に作った関数を探します。
関数名の頭にEvent がついている方を選ぶと以下のようなノードが出てきます。
右上にインターフェイスのアイコンがついています。
ここに最後の仕上げ。
これでWidgetブループリントは完成です。
コンテンツブラウザからこのWidgetを2つ複製します。
複製した1つ目を開いてテキストブロックの見た目を変更します。
パート名用です。
文字サイズを少し小さくして、カラーを変えています。
これで2つ目完成。
最期の3つ目は人名用。複製した残りのWidgetブループリントを改造します。
文字サイズとカラーを変更するのですが、ここで複数列の対応を追加します。
まずは編集モードをDesignに切り替えてキャンバスパネルを追加します。
その中に6つのTextBlockを入れて子供にします。
アンカーの設定はそれぞれ以下のように変更します。
レイアウトは下のような並びで配置しますが、
実際には1行に重なった状態にします。
テキストブロックの中は何も文字を入れないように空にします。
あとはカラーと文字サイズ、字詰め方向(Justify)を設定したら、Is Variable にチェックを付けて編集モードをグラフに切り替えます。
String型と、TextBlock型の配列変数を用意します。
TextBlock型は、Object Typesの中にあります。
6つのテキストブロックを配列に積みます。
移動するのは、キャンバスパネルになるので Slot as Canvas Slot ノードには、追加したCanvasPanelをつなぎます。
インターフェイスで仕込んだ StartMove関数(ここではEvent)の部分を以下のように改造します。
Parse Into Array ノードは指定した文字列(デリミタ)が見つかると分割して配列にしてくれます。
人名のWidgetはこれで改造完了です。
これですべてのWidgetブループリントが完成しました。
今回はこの辺にしておきます。
次回はデータの準備と表示する部分を書きます。
ではでは
わりと本気のコンボカウンター 《完結編》
いよいよ動作確認です。
前回の記事はこちら
わりと本気のコンボカウンター 《UMG編》 - みつまめ杏仁
わりと本気のコンボカウンター 《Widgetブループリント編》 - みつまめ杏仁
一揃いのアセットができたので、テストしてみます。
テスト用のレベルを開いた状態で、エディタを開きます。
まずはカウント用の変数を一つ用意。Int型です。
CreateWidgetから始めます。
CreateWidgetの ReturnValue ピンの上で Promote to Variable を選ぶと簡単に変数化できます。とりあえず表示位置を大まかに決めておいて、あとはバインド祭り。
Widgetの中に仕込んでおいた イベントディスパッチャーにバインドします。
バインドは「紐づける」という意味合いです。四角いピンとカスタムイベントをつないでおくと、Widget内でイベントディスパッチャーがCall されたタイミングでここに通知が来て、カスタムイベントが作動するというしくみです。
CreateWidgetした側は、好きなタイミングでWidgetに干渉できるのに対して、CreateWidgetされた側からは逆の干渉ができません。そこで用意されているのが、このイベントディスパッチャーを使ったデリゲートとインターフェイスという2つの仕組みです。
EventDispatcher をCallしてるノードと、Bindしてるノードにマウスカーソルを重ねると
デリゲートという用語が出てくるのが分かります。
今回インターフェイスは使っていませんが、これもGUIにはとても相性がよいです。
つぎに、カウントアップの呼び出し部分。
スペースキーを押すとカウントするようにしています。
最後にWidgetの関数に値を渡して完成。
再生してテストしてみましょう。
動画を貼りたかったのですが、直接はダメっぽいので諦めました。
消え方が派手だったり、確定した時の演出があると、最終のカウントがよりわかりやすくなります。
プレイヤーは視界の端で見てるので、多少派手なくらいがちょうどいいです。
というわけで
わりと本気で作ってみたコンボカウンターです。
デザイナーだけでこのようなモックアップを作ってテストしてもらい、プログラマに組み込みを依頼する流れでいけば、小さなイテレーションループで済みそうですがいかがでしょう。
ではでは
ステキなカウントライフを