2014年7月25日金曜日

【Unity、UniRx】オブジェクトをカラータイマーみたいに点滅させる


@Baiteen

ReactiveExtensionsがUnityでも使えるってのを今更知ったので、今更ながら使ってみた。その4。

やりたいこと

ReactiveExtensionsを使ってオブジェクトをカラータイマーみたいに点滅させる。

やったこと

(UniRxはインポート済み)
まずは、点滅させるためのSphereを追加(Sphereじゃなくてもいい)
んで点滅してるのがわかるようにPlaneを追加(Planeじゃなくてもいい)
んでResourcesフォルダ作って、その中に"self-illumin"ってMaterialを作っておく(ShaderをSelf-illuminにしてね)
それからC#Scriptを作成してコードを以下のように変更(今回もTestScriptにしました)
そしてTestScriptをSphereにドラッグ&ドロップしたら出来上がり
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UniRx;

public class TestScript : ObservableMonoBehaviour {

  /// 点滅速度
  public float Speed = 5f;

  /// 点滅時間[sec]
  public float DueTime = 3f;

  ///  RXのサンプルがAwakeだったので、ここに書きました。 
  public override void Awake ()
  {
    //参考サイト:http://neue.cc/2010/07/28_269.html

    //最初につけてあるShader
    var defaultShader = this.gameObject.renderer.material.shader;
    //光らす用のShader(Resourcesフォルダの中に"self-illumin"ってMaterialを作っておく)
    var illuminShader = Resources.Load( "self-illumin" ).shader;

    //マウスダウンされると値が発行される
    OnMouseDownAsObservable()
    //光らす用のShaderに切り替え&ライト追加。追加したライトを後続に渡す。
    //ここの書き方はあんまりよろしくない気がする。。。
    .Select(_ => {
      this.gameObject.renderer.material.shader = illuminShader;
      return this.gameObject.AddComponent();
    })
    //Updateで明るさ値更新してOnGUIのタイミングで明るさ値とライトを値として発行。
    .SelectMany(light => 
      UpdateAsObservable()
      .Select(__ => Mathf.Sin(Time.time * this.Speed))
      //OnGUIのタイミングで値を発行したいのでこれする。
      .CombineLatest(OnGUIAsObservable(), (sin,g) => new {sin, light})
    )
    //時間が来たら値の監視をやめて、Shader元に戻す&ライト削除
    .TakeUntil(
      Observable.Timer(TimeSpan.FromSeconds(this.DueTime))
      //Shaderを切り替える処理がメインスレッドじゃないと出来なかったのでこれした。
      .ObserveOnMainThread()
      .Do(_ => {
        this.gameObject.renderer.material.shader = defaultShader;
        Destroy(light);
      })
    )
    //TakeUntilで監視が終了するので、Repeatで繰り返す
    .Repeat()
    //値が発行されたらライトの明るさ更新
    .Subscribe(o => {o.light.intensity = Mathf.Abs(o.sin)*8f;});

    // If you use ObservableMonoBehaviour, must call base method ← サンプルにこう書いてますので、そのまま。
    base.Awake ();
  }
}


こんな感じ。
Hosted by UnityRoom.com

点滅の仕方がちょっとイビツだけどまぁいいや。
センスがないのはほっといて。
一応やろうと思ってた動きにはなったのでOKってことで。


スポンサーリンク

Related Posts Plugin for WordPress, Blogger...