Unity でオブジェクトをドラッグして移動させる using UniRx

やりたいこと:タイトルのまま

最近話題のUniRxを使ってみました.

using UniRx;
using UniRX.Triggers;
using UnityEngine;

public class DraggedObject : MonoBehaviour
{
    void Start()
    {
         this.OnMouseDragAsObservable()
            .TakeUntilDestroy(this)                      // このオブジェクトが破壊されるまで
            .Select(_ => Input.mousePosition)
            .Select(pos =>
            {
                pos.z = this.transform.position.z;
                return Camera.main.ScreenToWorldPoint(pos);
            })
            .Select(pos => new Vector3(pos.x, pos.y, this.transform.position.z))
            .Subscribe(pos => this.transform.position = pos);
    }
}

これだけで,左クリックからのドラッグが書ける! すごい! ただ,OnMouseDragAsObservable は,右クリックからのドラッグには反応しませんでした.

というわけで,右クリック判定のメモ(右クリックのみ)

this.UpdateAsObservable()
    .Where(_ => Input.GetMouseButtonDown(1))    // 右クリックの時
    .Select(_ => Camera.main.ScreenPointToRay(Input.mousePosition))
    .Select(x =>
    {
         RaycastHit rh;
         var hit = Physics.Raycast(x, out rh);   // オブジェクトへの当たり判定
         return Tuple.Create(hit, rh);
    })
    .Where(x => x.Item1 && x.Item2.collider.gameObject == this.gameObject) // 当たったか,また,あたった対象がこのオブジェクトか
    .Subscribe(_ => Debug.Log("Right!!"));

Virtualbox の仮想マシンの場所移動 (Windows7)

PCの容量足りないから,Virtualbox仮想マシンを外付けに移動したいと思ってたら, ぴったりの記事を発見.

VirtualBoxの仮想マシンフォルダ変更手順メモ - Qiita

ここの通りにやったらできた.

が,vagrantとの紐づけが壊れてしまった・・・.

移動した後,なんやかんやしてる時に,vagrant init とかしてしまい・・・.

どうしよう・・・と思っていたら,これまたぴったりの記事を発見.

Vagrantの仮想マシンとの紐付けの直し方 - ウチのメモ

ここの通りにやったらできた.

ついでに,マイドキュメントいかに作られてるvirtualboxの設定?関係の入ったフォルダ「.Virtualbox」の場所を移動したい場合は,環境変数に「VBOX_USER_HOME」を作って,そいつで指定してあげればいいらしいです.

Windos7 + Vagrant + virtualbox で,仮想OS(CentOS6.5) 環境構築

各ソフトウェアのバージョン

インストール方法

いろんなサイトにあるので割愛

発生した問題

vagrant up で起動しようとすると 「Booting vm...」 ってところで止まる.

解決策

vagrantfile の「config.vm.network "private_network", ip: "192.168.33.10"」を有効にし, 一旦virtualbox 側で仮想OSを立ち上げて,すぐにシャットダウン. その後,vagrant up すると起動した. なんでや・・・.

結論:Virtualbox で直接立ち上げた後なら,vagrant up で立ち上がる. PC起動ごとにやらなきゃダメ. なんでや・・・

vagrantfile内の

config.vm.provider "virtualbox" do |vb|
  vb.gui = true
  vb.memory = "1024"
end

を有効にすれば,vagrant up と同時に,仮想OSがGUIで立ち上がり,起動することが可能.

C# で自分のPCのIPアドレスを取得

// using System.Net; が必要

String hostName = Dns.GetHostName();    // 自身のホスト名を取得
IPAddress[] addresses = Dns.GetHostAddresses(hostName);

foreach (IPAddress address in addresses)
{
    // IPv4 のみを追加する
    if ( address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork )
    {
        // こんな感じで,コンボボックスに突っ込んだり
        //MyIps.Items.Add(address);
    }
}

OSC ( Open Sound Control ) のライブラリメモ

OSC便利!
って友人に言ったら「何をいまさら」と冷たくあしらわれました.
タンスの角に小指ぶつければいいのに.

というわけで,使ってみたOSCのライブラリに関するメモです.

C++
C
Unity (C#)
  • unity-osc

    • サイト:https://github.com/keijiro/unity-osc

    • ライセンス: 著者情報等がソフトウェア何に含まれてればよさそう

    • OSC の受信部分のみ,また,対応する型は,OSCの基本のもののみ

こんだけ揃えば,C++ で高速に解析したデータをUnityに送ったり,C#のUIからの制御信号をUnityに送ったりできますね!
他にも何個か試したけど,使いやすかったのは上記のものでした.
なんか他にいいのがあったら,ぜひ教えてください.

ちなみに, opensoundcontrol.org に,OSCのライブラリがたくさん載っています.
他のライブラリを探すときは,上記サイトを参考にするといいかもしれません.

OSC ( Open Sound Control ) の C++ ライブラリ oscpack を使ってみた

OSC ( Open Sound Control ) とは,PC等において音楽演奏データをネットワーク経由でリアルタイムに共有するための通信プロトコルなわけですが,それを使ってみたくなって,いろいろライブラリを探したところ,oscpack というのがよさそうとのことで,早速ダウンロードしてみました.

OSC に関する詳しい情報はgoogle先生に聞くといっぱいでてくると思います.
が,さらっと私の理解を書いておくと,

  • 基本はUDP通信

  • 送信する情報の形式は以下の様な感じ

    • /aaa/bbb/ccc 123 0.5 "へろー"

      • OSC Message: 上のアルファベットの部分ね

      • aaa を起点にした階層構造になってる

      • 受け手はこの情報を元に,どの変数なりオブジェクトに値を渡すか判断すればよい

      • 要はアドレス

    • OSC Argment: 後半の数字や文字列の部分ね

      • OSC Message で示されたアドレスに渡す値,何個でもOK (まぁ,実装次第だが)

独自の取り決めで送受信するよりも,OSC に従った方が,メンテしやすいし,他人の書いたプログラムとの連携も録りやすいってのがメリットかなぁ.

さて,こっからがoscpackについてです. oscpackには,UDP送受信,送信情報を一つにまとめるための関数,受信した情報からOSC Message や OSC Argment をパースする関数等が含まれています.
ですので,後は,送信側と受信側で OSC Message を取り決め,パース後の挙動を書けばいいわけです.

oscpack のダウンロードは oscpack のホームページから可能です.
http://www.rossbencina.com/code/oscpack
ライセンスはMITだそうです.

OSは,windows, linux, mac をサポートしているようで,私は windows7, visual studio 2010 でコンパイルしました.
vs2010 でのコンパイル方法は,ダウンロードして解凍したフォルダに含まれるREADMEに書いてあります. といっても,下記のコマンドを実行するだけ.

cmake -G "Visual Studio 10"

コマンドを実行してできた TestOscpack.sln をビルドすれば,oscpack.lib やサンプルが出来上がります.

試に,コマンドプロンプトからOSCDump.exe を起動し,vs2010のデバッグから SimpleSend を行うと,挙動が分かりやすいと思います.

OSCでは,基本的には,bool や double のデータは扱わないようになっているみたいですが,oscpackではそのあたりも扱ってくれるようです. ただし,他のライブラリが必ずしもサポートしているとは限らないため,別プログラムとの通信の際には注意が必要です. どういったデータ形式が使用できるか等は,下記のサイトを見るのがよいと思います.
http://veritas-vos-liberabit.com/trans/OSC/OSC-spec-1_0.html

ところで,OSCって数値配列とかって対応してないんでしょうか・・・? この辺,まだ調べ切れてないや・・・. ちゃうちゃう,byte[]にして送ればええんやーーーーーーー.(自己解決

Unityの立方体のuvをいじくる

Visual Studio Tools for Unity 1.9 公開されましたね.
UnityのC#Visual studio で書けるってすばらしい.
えっ? Express edition では使えない!? (゚д゚)!

orz

気を取り直して,今日の本題です. Unity の立方体の各面に,それぞれ別の絵を表示させたい時ってありすよね.
例えば,サイコロとか.
別のソフトで,テクスチャ込の立方体モデルを作ってそれを読み込ませるのが順当な手だとは思うんですが,それはめんどくさい o(`ω´*)oプンスカプンスカ!!
というわけで,C#でメッシュのuvをいじってなんとかしてみたいと思います.
(そっちのがめんどくさいだろというツッコミはスルー

UnityのCubeは六面体,当然ですが,面が6個あります. その面は4つの頂点を持っており,それぞれの面の頂点を別物ととらえると6x4=24個の頂点があります.
この24頂点のuv値を,表示させたい画像に合わせて変更してあげればいいわけです.

それぞれの頂点は,下図のような関係にあると思われます.
(まちがってたらごめんんさい 

f:id:rinor:20140808161155p:plain

この図を参考に,スクリプト上で,gameObjectから取得したメッシュのUVを書き換えてあげればOKです.
ソースコードは以下のような感じにして,下記のようなサイコロ画像を読み込ませればたぶん大丈夫です.

f:id:rinor:20140808164621p:plain

using UnityEngine;

public class UVChange : MonoBehaviour
{

    Vector2[] uv = new Vector2[24];

    void Awake()
    {
        // 1の面
        uv[2].x = 0.0f; uv[2].y = 0.0f;
        uv[3].x = 1.0f / 6.0f; uv[3].y = 0.0f;
        uv[0].x = 0.0f; uv[0].y = 1.0f;
        uv[1].x = 1.0f / 6.0f; uv[1].y = 1.0f;

        // 2の面
        uv[4].x = 1.0f / 6.0f; uv[4].y = 0.0f;
        uv[5].x = 2.0f / 6.0f; uv[5].y = 0.0f;
        uv[8].x = 1.0f / 6.0f; uv[8].y = 1.0f;
        uv[9].x = 2.0f / 6.0f; uv[9].y = 1.0f;

        // 3の面
        uv[23].x = 2.0f / 6.0f; uv[23].y = 0.0f;
        uv[21].x = 3.0f / 6.0f; uv[21].y = 0.0f;
        uv[20].x = 2.0f / 6.0f; uv[20].y = 1.0f;
        uv[22].x = 3.0f / 6.0f; uv[22].y = 1.0f;

        // 4の面
        uv[19].x = 3.0f / 6.0f; uv[19].y = 0.0f;
        uv[17].x = 4.0f / 6.0f; uv[17].y = 0.0f;
        uv[16].x = 3.0f / 6.0f; uv[16].y = 1.0f;
        uv[18].x = 4.0f / 6.0f; uv[18].y = 1.0f;

        // 5の面
        uv[15].x = 4.0f / 6.0f; uv[15].y = 0.0f;
        uv[13].x = 5.0f / 6.0f; uv[13].y = 0.0f;
        uv[12].x = 4.0f / 6.0f; uv[12].y = 1.0f;
        uv[14].x = 5.0f / 6.0f; uv[14].y = 1.0f;

        // 6の面
        uv[6].x  = 5.0f / 6.0f; uv[6].y  = 0.0f;
        uv[7].x  = 6.0f / 6.0f; uv[7].y  = 0.0f;
        uv[10].x = 5.0f / 6.0f; uv[10].y = 1.0f;
        uv[11].x = 6.0f / 6.0f; uv[11].y = 1.0f;
    }



    // Use this for initialization
    void Start()
    {
        MeshFilter mf = gameObject.GetComponent<MeshFilter>();
        mf.mesh.uv = uv;
    }

    // Update is called once per frame
    void Update()
    {

    }
}