maimai_jp's blog

twitterでは書ききれないことなどをこちらに。

UniRx4.8以降で作るUIサンプル【長押し編】

Web上にあるUniRxのサンプルうごかねぇぇぇぇぇぇえええ!!!!

と、一時間ぐらいでサクッと作れると思っていたコントローラ操作まわりの実装のためにAsset縛りGameJamの一日目を潰しました。どうもこんにちわ。

というわけで、とりすーぷさんの以下の記事にもありますが「UniRxの記述方法が大幅に変更されて」います。

 

qiita.com

作者の@neueccさん曰く非推奨であり、UniRx 4.8以降でサポートされなくなりました。
代わりに後述のObservableUpdateTriggerを使いましょう。

 

以前はObservableMonoBehaviourの継承によって実装がされていましたが、現在はTrigger式に変更されています。

その関係で、「2015年4月以前に記述されているUniRxのサンプルの大半が動かない」という罠に陥りました。

……いや、散々製作者のneueccさんとかがUniRx勉強会とかで解説されていたりしてたのを、思い出してみると確かに言ってたんです。ええ。

でも、実はその勉強会時点ではUniRx自体をあんまり触ってなくて、そもそも「変更点があった」ということの前に「変更前の仕様」自体がピンときてなかったんです。ええ。

 

そんなわけで、こんなものができました。

 

vine.co

ソースはこちら。

gist.github.com

 

上のサンプルは、UGUIのボタン用Imageに色をつけて、chargePowerに従ってAnchorのMaxをそれぞれ0→1にしている感じです。

よくよく考えると、たぶん今までやってきたこととさして変わらないことに気が付くと思います。

  1. GetButtonDownで判定する
  2. TrueならTimerを初期化してPressedフラグをONにする
  3. GetButtonの間、TimerにdeltaTimeを加算する
  4. GetButtonUpがTrueになったら、Timerの値を処理する

これがfire1ChargeStreamという一行のクエリ文で定義されているのが面白いわけですよ。if文もswitch文も書いてないのに。(もちろん、ラムダ式の右辺を{~~~}という形式にすることで複雑な分岐も記述できます。)

これ、書いてみるとわかると思います。操作系をStreamによってシーケンシャルに記述できることって、ものっそい武器になりそうなんですよ。一行のクエリ文で定義できることが。

  • ある一定時間内に●●できたらxxという効果を発生させる

っていうアクションゲームではよくあるシステムですけど、時系列が入る判定とかってなかなかやれないですよね。同時押しぐらいだったらいけるでしょうけど、時系列でボタン同士の関係がアクションとして絡んだりすると、タイマー判定やら何やらでUpdateのコードが煩雑になりがちですし。

でも、UniRxだと一通りの内容を関数内に分散させることなく一つのStreamとして扱うので、「Excelでのコマンドリスト」から「コマンドの生成」すら可能になりそうで。

これはなかなか捗る。次のGameJamが楽しみです。

 

追記:

当初、Web上のソースから"RepeatUntilDestroy"の部分を"Repeat"で実装していました。

しかし、これで実行するとプレイヤーの再生終了時に「Unityがハングする」という怪現象が発生しまして。

ひとまずTwitter上でぶん投げてみたところ……

……とneueccさんから回答いただきまして、無事解決しました。

どうやらOnCompletedが発行されるタイミングがRepeat前に処理されてしまうことで無限ループが発生してしまう場合があるようで、このRepeatに条件付帯されたRepeatUntilDestroyを使うことが推奨されるようです。