質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

1971閲覧

【unirx】タップ時の処理にThrottleFirstでディレイをかけても複数回処理が呼び出されてしまう

gimn

総合スコア39

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2021/05/28 15:24

編集2021/05/29 05:13

下記コードのように、オブジェクトのタッチを検知して、タッチ時の処理を行うコードを記載しました。
タップされると、TouchButton()を呼び出します。
TouchButton()の中では、
・currentCoolTimeを設定(仮に5秒とする)
・コルーチンで0.1秒ごとにcurrentCoolTimeを0.1減少させていく
・currentCoolTimeが0になったら終了
という流れの処理が行われます。
クールタイム中は押下できないようにWhereで条件を設定していますが、連打した際に稀に複数回呼び出されてしまっているような挙動をしておりました。※明らかに5秒より早いクールタイムの経過となることがある
そのため、ThrottleFirstを追加して短時間でのボタン連打を抑止しようとしましたが、こちらも結果は変わらずでした。

自分がThrottleFirstの機能を誤解しているのか、このような動作となる原因についてご存じありませんでしょうか。

c#

1 gameObject.GetComponent<TapGesture>() 2 .TapAsObservable() 3 .ThrottleFirst(TimeSpan.FromMilliseconds(1000)) 4 .Where(_ => currentCoolTime.Value == 0) 5 .Subscribe(_ => TouchButton()) 6 .AddTo(this.gameObject);

※TapGestureはTouchScriptというAssetの機能で、TapAsObservableはTapGestureの検知用に拡張して実装されています。

【追記】
いろいろと検証してみたところ、どうやら連打ではなく特定のタイミングで押下した際に複数処理が呼ばれているようです。
タイミングとしては、クールタイムが丁度終了となる当たりでタップするとほぼ再現しました。
また、複数処理が呼ばれているといっても、コルーチンで行っているクールタイム計算の処理のみが複数呼ばれているようなのです。
※押した際にカウンタを計上するようにしてみましたが、カウンタは1しか増加しなかったため

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/05/29 20:17

TouchButtonからコルーチンで行っているとの事ですので、コルーチンの開始と終了を確認してみては? ThrottleFirstにcoolTimeの最大値を与えればいいんじゃ?って思ったのですが、ダメなんでしょうか? ThrottleFirst(TimeSpan.FromMilliseconds(coolTime)) 書いてみたら動的に変更が出来なかった(最初にあたえられた値を保持してしまうヤツ)ので、coolTime変更時は破棄して走りなおすっていう強引?な方法しか思いつきませんでしたが
gimn

2021/06/01 14:57

回答ありがとうございます。 返答遅くなり申し訳ございません。 ご指摘の通りThrottleFirstをcoolTimeとして扱う方法も考えましたが、将来的にcoolTimeは動的に変更する可能性もありThrottleFirstでの管理では実現は可能かもしれませんが現実的ではないかなというのが正直なところです。 以後もいろいろな検証を行った結果、StartCoroutineする前にStopCoroutineをかけて複数起動を抑制する方法をとってみましたが、今のところ表記の事象は発生しなくなりました。 根本的な原因は結局わからない状況ですが、回避方法となり得る策はありましたので、ひとまずはこれで対処しようかと思います。
guest

回答1

0

自己解決

根本的な原因解明には至っておりませんが、ひとまずの回避策として
・StopCoroutine ⇒ StartCoroutune
と実行して、コルーチンの2重呼び出しを防ぐことができました。

投稿2021/06/01 14:59

gimn

総合スコア39

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/06/03 06:48

public IntReactiveProperty coolTime = new IntReactiveProperty(1000); private void Start() { IDisposable inputStream = new SingleAssignmentDisposable(); coolTime.Subscribe(time => { inputStream?.Dispose(); inputStream = this.UpdateAsObservable() .Where(_ => Input.GetKeyDown(KeyCode.Space)) .ThrottleFirst(TimeSpan.FromMilliseconds(time)) .Subscribe(_ => Debug.Log("Input")); }); } UniRxは私も勉強中なのでこういったやり方が正しいのか?このやり方だとバグる?もっといい方法があるとも思う。のですが、一応coolTime.Valueの変更で可能になります。 coolTimeが変更されたら走らせ直す、ってコードです。
gimn

2021/06/05 05:33

回答ありがとうございます。 なるほど、そういう書き方もできるのですね。参考にさせていただきます。 私もUniRxはまだ触りたてで一部機能しか理解が及んでおりませんが、これから理解を深めていければよいなと思っております。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問