@Baiteen
ReactiveExtensionsがUnityでも使えるってのを今更知ったので、今更ながら使ってみた。その6。
やりたいこと
ReactiveExtensionsを使ってクリック回数をトースト表示する。やったこと
(UniRxはインポート済み)まずは、クリックするためのSphereを追加(Sphereじゃなくてもいい)
前回のなごりでPlaneを追加(Planeじゃなくてもいい)
トースト表示するためのText追加(せっかくなのでuGUI使いました)
それからC#Scriptを作成してコードを以下のように変更(今回もTestScriptにしました)
そしてTestScriptをSphereにドラッグ&ドロップしたら出来上がり
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UniRx;
static class ColorExt
{
///
/// Textのアルファ値をセットする拡張メソッド
///
/// uGUIのText
/// アルファ値
public static void setA (this UnityEngine.UI.Text text, float a)
{
text.color = new Color(text.color.r, text.color.g, text.color.b, a);
}
}
public class test1script : ObservableMonoBehaviour
{
/// トースト表示用オブジェクト
public GameObject Toast;
/// Scanで匿名クラス使うとなぜかエラーするので、クラス定義
private class Delta
{
public float time{ get; set; }
public float offset{ get; set; }
public Delta(float t, float o){ time = t; offset = o; }
}
///
/// 指定秒間だけEveryUpdateを発行する
///
///
/// 秒
private IObservable TakeSec (double value)
{
//0秒〜経過秒が値として発行される
return Observable.EveryUpdate().Scan(
new Delta( 0, Time.time)
, (a, t)=>new Delta( Time.time - a.offset, a.offset)
).Select(delta => delta.time)
.TakeUntil(Observable.Timer(System.TimeSpan.FromSeconds(value)));
}
/// RXのサンプルがAwakeだったので、ここに書きました。
public override void Awake ()
{
//参考サイト:http://neue.cc/2010/07/28_269.html
//トースト用オブジェクトからuGUIのTextを取り出して、透明にする
var text = Toast.GetComponent ();
text.setA(0);
//nueuccさんのアドカレ記事をパクりました
//クリック回数をトースト表示
OnMouseDownAsObservable ()
.Buffer (OnMouseDownAsObservable ().Throttle (System.TimeSpan.FromMilliseconds (250)))
.Select (xs => xs.Count)
.Do(cnt => text.text = string.Format ("{0} clicks", cnt))
.SelectMany(cnt =>
//1秒かけて0→1、また1秒かけて1→0ってなってほしいんだけど、0→1、1→2ってなる。意味不明。
Observable.Concat(TakeSec(1).Do(t=>text.setA(t)), TakeSec(1).Do(t=>text.setA(2-t)))
).Subscribe (t=>Debug.Log(t));
// If you use ObservableMonoBehaviour, must call base method ← サンプルにこう書いてますので、そのまま。
base.Awake ();
}
}
こんな感じ。
Hosted by UnityRoom.com
どうにか思ったとおりの動きになったんだけど、理解できない部分がいくつか。
・Scanのseedを匿名クラスにすると、なぜかCannot implicitly convert type `anonymous type' to `anonymous type'って怒られる
・1秒で終わるObservableをConcatで2つ繋げると、なぜか単体で動かすのと違う動きになる、気がする、、、
追記
neueccさんからアドバイス頂いてScanの理解できない件解決しました。
timeの型がintとfloatになってるだけでした。
seedをnew {time=0f, offset=Time.time}にしたらOKでした。はずかし。
Concatの件もいろいろ試してたら思った感じの動きになりました。
Observable.Concat(TakeSec(1).Do(t=>text.setA(t)), TakeSec(1).Do(t=>text.setA(2-t)))
を
TakeSec(1).Do(t=>text.setA(t)).Last().SelectMany(_=>TakeSec(1).Do(t=>text.setA(1-t)))
てしたらそれっぽくなりました。全然わからん。



























