「C#」カテゴリーアーカイブ

UnityでPhotonネットワークその2

Unityで作成中のイベント用アプリの作成メモです

現在作成中のアプリですが,同期などの関係から(たぶん)全員が同じ部屋に入ることが必要です.

そこでいろいろ面倒が発生します(以下,photonのレベル別マッチメイクのスクリプトなどから流用しています)

(1)photonネットワーク接続直後にはroom listを取得してもゼロが返るっぽい.不確実だけど対抗策は

	void OnReceivedRoomListUpdate()

で,リストがアップデートされてから,ルームリストをチェックする.

(2) PhotonNetwork.CreateRoom()はどうもエラーが起きやすい.ので,確実にその名前のルームが無いことを確認しなくてはいけない(そこで上記のルームリストを使うけど,タイミングが,,,

(3)そこでおおまかな流れとしては,Photonに接続して,ロビーに入ったら,そのままにしておいてリストのアップデートを待つ.アップデートされない時のために,5秒くらい待つ関数を入れるか思案中(未実装).リストがアップデートされたら,同名のルーム名がないかチェックして,あればそこに入室,なければ作成をする.

ここまでのスクリプトです.

using UnityEngine;
using System.Collections;
using Hashtable = ExitGames.Client.Photon.Hashtable; //need for generate hashtable

public class photonsystem : Photon.MonoBehaviour {
	public string objectName;
	private bool connectFailed = false;

	//set player name
	private string playerName = "GuestAAA";	
	//set room name
	private string roomName = "liub2";//liubという専用のルーム名を作成



	void OnJoinedLobby() {
			Debug.Log("ロビーに入室");
			//ランダムにルームへ参加

		//thi wrok
		//PhotonNetwork.JoinRandomRoom();// join to random room tempolary
		//until here//

		}



	void OnReceivedRoomListUpdate()
	{
		CreateRoom ();
	}


	/////test 24th January

	public void CreateRoom (){
		RoomOptions roomOptions = new RoomOptions ();
		roomOptions.isVisible = true;
		roomOptions.isOpen = true;
		roomOptions.maxPlayers = 50;//test 50 max players
		roomOptions.customRoomProperties = new ExitGames.Client.Photon.Hashtable (){{"CustomProperties", "111"},{"r", "0.2"}};
		roomOptions.customRoomPropertiesForLobby = new string[] {"CustomProperties"};

		if (PhotonNetwork.GetRoomList ().Length == 0) {
			PhotonNetwork.CreateRoom (roomName, roomOptions, null);
			return;
		}
		foreach (RoomInfo roomInfo in PhotonNetwork.GetRoomList()) {
			if (roomInfo.name != roomName) {
				PhotonNetwork.CreateRoom (roomName, roomOptions, null);
			} else {
				//isRoomEnabled = true;
				PhotonNetwork.JoinRoom(roomName);
			}
		}
	}






		/// 部屋に入るとき呼ばれます。
		/// これは参加する際だけでなく作成する際も含みます。
		void OnJoinedRoom() {
		Debug.Log("部屋に入室" + PhotonNetwork.room.name);

		//ゲームオブジェクト作成する時用
		//GameObject cube = PhotonNetwork.Instantiate(objectName, Vector3.zero, Quaternion.identity, 0);

		//make cube
		//GameObject player = PhotonNetwork.Instantiate("testobj", this.transform.position, this.transform.rotation, 0);
		}

		/// JoinRandom()の入室が失敗した場合に後に呼び出されます。
		void OnPhotonRandomJoinFailed() {
		//void OnPhotonJoinFailed() {
			Debug.Log("部屋入室失敗");
			//名前のないルームを作成
		//	PhotonNetwork.CreateRoom(null);

		/////以下はテスト用えコメントアウトしています 
		//create custom property
	//	RoomOptions myOptions = new RoomOptions ();// require use custom property
	//	myOptions.isVisible = true;
	//	myOptions.isOpen = true;
	//	myOptions.maxPlayers = 50;
	//	myOptions.customRoomProperties = new ExitGames.Client.Photon.Hashtable (){{"CustomProperties", "111"},{"r", "0.2"}};
	//	myOptions.customRoomPropertiesForLobby = new string[] {"CustomProperties"};

		// ルームの作成
	//	PhotonNetwork.JoinOrCreateRoom(roomName, myOptions, null);


		}


		void Awake() {
			//マスターサーバーへ接続
			PhotonNetwork.ConnectUsingSettings("v0.1");


		if (PhotonNetwork.playerName==null)
		{
			//ランダムにプレイヤーの名前を生成
			this.playerName = "Guest" + UnityEngine.Random.Range(1, 9999);
			//Photonにプレイヤーを登録
			PhotonNetwork.playerName = this.playerName; 
		}else{
			//Photonにプレイヤーを登録
			this.playerName = PhotonNetwork.playerName;
		}

		}


	//部屋作成に成功したときにコール
	public void OnCreatedRoom(){
		Debug.Log("OnCreatedRoom");
	}
	//接続が切断されたときにコール
	public void OnDisconnectedFromPhoton(){
		Debug.Log("Disconnected from Photon.");
	}
	//接続失敗時にコール
	public void OnFailedToConnectToPhoton(object parameters){
		this.connectFailed = true;
		Debug.Log("OnFailedToConnectToPhoton. StatusCode: " + parameters + " ServerAddress: " + PhotonNetwork.networkingPeer.ServerAddress);
	}

	}

 

Unityでphotonネットワークを使って同期

※この方法は通常の使い方と異なります

サンプルのほとんどは,自分のキャラを相手側に出現させるという方法ですが,これはライトの色をマスター側が操作し,クライアント側の色を変えるというものです.

ライブイベントでみんなのスマホの色を同時に変更したい!を実現させる一つのアイデアです.

unityPhoton

赤線の部分を

操作される側(クライアント)は Takeoverに

操作する側(マスター)はFixedにします.

これでマスター側で色を変えると相手側も同じ色になります

その他のスクリプトは後日

Unity5でmic inputが反応しない件

micinputのサンプルがどれを試してもうまくいかない.

サンプルの記事ですと,コンソールにずっとゼロが表示されて音量が変化しません.

(最初に参考にさせていただいたスクリプト http://www.jonki.net/entry/20130607/1370622815 )

思い悩んで2日目,グーグルさんに1年以内の記事に限って検索するとその答えが載っていた.

まずはスクリプト(改変済み)

using UnityEngine;
using System.Collections;
//script source from web sample
//
public class micinput : MonoBehaviour {

	void Start()
	{

		//check
		foreach (string device in Microphone.devices) {
			Debug.Log("Name: " + device);
		}
		//
		GetComponent<AudioSource>().clip = Microphone.Start(null, true, 999, 44100);  // マイク入力
		GetComponent<AudioSource>().loop = true; // ループ再生にしておく
		//GetComponent<AudioSource>().mute = true; // Unity5ではコメントアウトうる
		while (!(Microphone.GetPosition("") > 0)){}             // マイクが使えるまで待つらしい
		GetComponent<AudioSource>().Play();                                           // 再生しないと音量をチェックできない
	}


	void Update()
	{
		float vol = GetAveragedVolume();
		print(vol);    
	}

	float GetAveragedVolume()
	{ 
		float[] data = new float[256];
		float a = 0;
		GetComponent<AudioSource>().GetOutputData(data,0);
		foreach(float s in data)
		{
			a += Mathf.Abs(s);
		}
		return a/256.0f;
	}


}

その対処方法

(ソース http://qiita.com/CST_negi/items/c8862f8d05dd9e871917 )

CreateEmptyで空のオブジェクトを作成

そこにスクリプトをアサインします

ミキサーの画面を呼び出し,[+]ボタンでミキサーを作成(ミキサなんてはじめてつこうたよ,,)micmixer

そのミキサのフェーダーを-80dbまで下げる(でないとハウリングおこしました)

micmixer2

上で空のオブジェクトに割り当てたたスクリプト(画面最下段の赤線)にAudio Sourceを割り当てます.

Outputに先ほど作成したミキサー(なぜかMasterと表示される)をアサインします

micmixer3

無事float値で取得できました

Jsとcs間でのデータの受け渡し

JSとCS間ではいくらstaticが神の領域といえど,変数やクラスは呼び出せません.

とはいえ.いくつかの条件で橋渡しができます.

それにはいくつかのルールがあります.

(1)特定名のフォルダを作成し,呼ばれるスクリプトはそこに入れる

特定名のフォルダとは,Standard Assetsか,Pluginsとなります.ただ,Standard Assetsは,StandardAssetsパッケージを読み込んだ際に作られるフォルダとたぶん同名なので何かと不安.そこでPluginsフォルダを作成し,呼ばれるスクリプトはそこに入れる.

(2)必ずGameObjectにアサイン

呼ぶ側のスクリプト,呼ばれる側のスクリプトともになにかのGameObject(create emptyでもOK)にアサインする必要があります.以下の呼び出す側例はthis.○○を使っているので,同じGameObjectにアサインしています.試してはいませんが,find○○を使えば別の場所にアサインしていても呼び出せるのでは?

(3)呼ぶ側のスクリプトは特定フォルダ以外で

整理が面倒でも,呼び出す側のフォルダはPluginsフォルダ以外の場所に保存してください.なんだかエラーがでます.

スクリプト例

呼ばれる側

ーこのスクリプトはPluginsフォルダに入れる

#pragma strict
var neko : int = 100;
function Start () {
}

function Update () {
}

function test(){ //sample of call method
print("neko"); //return text message
}

呼び出す側

ーこのスクリプトはPluginsフォルダ以外に保存

using UnityEngine;
using System.Collections;

public class Scriptcall : MonoBehaviour {
	private calledVar jsScript;//calledVarはjsのファイル名.これを変数の型にするって?謎
	// Use this for initialization
	void Awake () { //Awakeは初回に1回のみ呼び出される関数
		jsScript = this.GetComponent<calledVar>(); //このオブジェクトついてるコンポーネントを呼び出すというもの
	}


	void Start () {
	
		Debug.Log (jsScript.neko); //これでjsで設定したint10が見えます


	}
	// Update is called once per frame
	void Update () {
		jsScript.test ();//これでjs内のfunctionも実行できます
//		Debug.Log (jsScript.neko);
	}
}

なぞだらけですが,これで動くみたいです.

UnityのUIーuguiについてその1くらい

UnityのGUI=uGuiについてのスクリプトとの連携について質問があったので,回答.

そのまえにVer4.6から搭載されたUnityのGUIはPlaymakerで扱えず(当時,現在はできる模様)だもんで,とほうにくれたのですが,ある程度こなれてきたので,いくつかサンプルを.

ところでUnityには以前nGUIという素晴らしいシステムがあったのですが,検索するとそちらがまだまだヒットします.

Unityのguiについて検索する場合は,ugui(ウグイ)と打ち込んで検索してみください.高い確率でunityのguiに関する情報が出てきます

 

ここから本題

今回はmyUItestというc#のスクリプトを書きます

初期状態はこう

using UnityEngine;
using System.Collections;

public class myUItest : MonoBehaviour {

	// Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () {
	
	}
}

これに,UIを使えるようにライブラリを読み込みます.3行目を追加しています.

using UnityEngine;
using System.Collections;
using UnityEngine.UI; //ui system use

public class myUItest : MonoBehaviour {

	// Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () {
	
	}
}

つぎに構造を考えます

1)UIに直接スクリプトをアサインする場合

2)UIとは別のところでスクリプトをアサインする場合=複数のUIを連携させたい場合

この2パタンで異なります.今回は後者でいきます.

ーー後日まとめる

テクスチャローダー

テクスチャローダー

using UnityEngine;
using System.Collections;
using UnityEngine.UI; //ui system use
using System.IO; //file save

public class texLoader : MonoBehaviour {

public string url = "";
public string url2 = ".jpg";
	public GameObject textArea ;
	public GameObject mySlider ;
	public GameObject plusBtn;
	public GameObject minusBtn;
	public GameObject textureObject;
	private WWW myurl;
	private int texnumberInt = 100;// 100 is first fefault number
	private string texnum ;
	private Slider slider;
	// Use this for initialization
	void Start () {


		slider = mySlider.GetComponent <Slider> ();
		slider.onValueChanged.AddListener((value) => {
			texnum = value.ToString();
		});


		texnum = "" + texnumberInt;//
		textArea.GetComponent<Text>().text = texnum;
		StartCoroutine ("loadTex");

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



	}


	public void sliderval(float val){
		texnum = val.ToString();
		textArea.GetComponent<Text>().text = texnum;

		StartCoroutine ("loadTex");
		//Debug.Log (texnum);
	}


	public void oneplus(){
		slider.value ++;
	}

	public void oneminus(){
		slider.value --;
	}



	private IEnumerator loadTex() {
		myurl = new WWW(url + texnum + url2);
		//Debug.Log (texnum);
		yield return myurl;

		// file write

		//File.WriteAllBytes( Application.persistentDataPath + "/" + Path.GetFileName(myurl.url), myurl.bytes );
		File.WriteAllBytes( "./myTex", myurl.bytes );


		Renderer renderer = textureObject.GetComponent<Renderer>();
		renderer.material.mainTexture = myurl.texture;
	}

}

 

キャラ選した色をキャラに与える

説明(略)

キャラの数じゃなく色を換えることで選択幅を増やしてる

もちろん,キャラ自身も変えられるがその場合はresorceあたりを使うといけるはず

Playerprefsに入れたキャラ名から色を決めてアサインするスクリプト

using UnityEngine;
using System.Collections;

public class setMaterial : MonoBehaviour {

	//変数宣言
	public Renderer myIka;
	public Renderer myTako;

	private string matname1;
	private string matname2;

	void Start () {
		materialSet (); //面倒くさいんで下にfunction作って呼び出すことに
	}
	
	// Update is called once per frame
	void Update () {
	
	}

	
	void materialSet(){ //というfunction作った
		matname1 = PlayerPrefs.GetString("matName1"); //距離から得られたキャラの名前をPlayerPrefsに入れあって,それを呼び出す
		matname2 = PlayerPrefs.GetString("matName2"); 
		//PlayerPrefsはシーン遷移で使うのが良いかと思います

		myIka = GameObject.Find("ikaName").GetComponent<Renderer>(); //名前でキャラを探しそのレンダラーをmyIkaに入れる
		myTako = GameObject.Find("takoName").GetComponent<Renderer>();

		//アサインされているマテリアルの色を色名で変更.たぶんHexも使えるはず
		//4択だったのでコピペ.caseとか使った方がもっとキレイになるのだろうけど,,
		if (matname1 == "ika01") {
			myIka.material.SetColor("_Color", Color.blue);
		}
		if (matname1 == "ika02") {
			myIka.material.SetColor("_Color", Color.green);
		}
		if (matname1 == "ika03") {
			myIka.material.SetColor("_Color", Color.white);
		}
		if (matname1 == "ika04") {
			myIka.material.SetColor("_Color", Color.yellow);
		}

		//tako用
		if (matname2 == "tako01") {
			myTako.material.SetColor("_Color", Color.blue);
		}
		if (matname2 == "tako02") {
			myTako.material.SetColor("_Color", Color.green); 
		}
		if (matname2 == "tako03") {
			myTako.material.SetColor("_Color", Color.white); 
		}
		if (matname2 == "tako04") {
			myTako.material.SetColor("_Color", Color.yellow); 
		}

	}

}

 

特定の日付までのカウントダウンを作る

とあるイベントまでのカウントダウンタイマーの例です.

C#ですとこんな書き方があります.

using UnityEngine;
using System.Collections;
using System;//.netフレームワークを使います一行上のものと一緒?
using UnityEngine.UI;   // UIを使います.UI使用時は必須

public class countTime : MonoBehaviour {
	System.DateTime mynow;//日付形式の入れ物作成(以下2つも)
	System.DateTime date2;
	System.DateTime date1 = new DateTime(2015, 4, 2, 18, 30, 0, DateTimeKind.Local);//カウントダウン終了時刻を時刻形式で設定
	string myString;//日付表示のための文字の入れ物
	string myString2;//ん?これ未使用?
	bool countdSW = false;//これも未使用?

	public Text countDownTime;//unity UIのTextコンポーネントをプロパティ画面でアサインできるように準備
	void Start () {

		// 現在時刻の取得
	mynow = DateTime.Now;//これ無意味ですが,気持ちの問題です

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

			
						mynow = DateTime.Now;//最新時刻を取得
		if (mynow < date1) {//日付の入れ物同士は比較演算子が使えますので,カウントダウン終了時刻と現時間を比較

						TimeSpan span = date1 - mynow;//Timespanという時間の長さを入れる専用の入れ物を作ってspanに入れる.これ.NETらしい

						myString = string.Format ("{0:00}h{1:00}:{2:00}:{3:00}", span.Days, span.Hours, span.Minutes, span.Seconds); //これも未使用?
						countDownTime.text = string.Format ("{0:00}d{1:00}h{2:00}m{3:00}s", span.Days, span.Hours, span.Minutes, span.Seconds);//残時間spanから各時間要素を取り出す {0:00}はその表示形式の設定ルール

				} else {
						countDownTime.text = "00d00h00m00s";//カウントダウンを越えたら0を入れる.ここに別のテキストを入れてもいいかも
				}
		}



}

ポイントは

1.日付形式 System.DateTime で変数作成

2.時間の長さを入れる TimeSpan で変数作成

3.日付形式の変数同士で > や <が使える

4.stringのフォーマット形式{0:00}{1:00}など

です

iTweenのonCompleteがおかしい

iTweenの処理後の操作でoncompleteを使うけど,指定した関数に飛ばない.

DebugLogを見ると飛んでいるようだけど,やってくれない.

うまくいかなかった例

iTween.FadeTo(obj, iTween.Hash("alpha", 0, "time", 0.4f,"oncomplete","boolReset","oncompletetarget", obj));

function boolReset(){
//bool reset
}

 

iTween.FadeTo(obj, iTween.Hash("alpha", 0, "time", 0.4f,"oncomplete","boolReset"));

function boolReset(){
//boolreset
}

 

うまくいった例

iTween.FadeTo(obj, iTween.Hash("alpha", 0, "time", 0.4f,"oncomplete","boolReset","oncompletetarget", gameObject));

ほげぇ,,,

UnityでARアプリ

UniyにVuforiaを入れてARアプリ.
簡単に作成できますが問題が.

Prefabでオブジェクトを作成(instantiate使って)したときに,ARマーカー非認識時でも隠したい見えちゃう問題です.

解決法.staticなブールを置いて,状態をチェックする.

(1)原因のおそらく
Vuforiaのスクリプトは子オブジェクトまでを配列に読み込んでrenderをON/OFFさせるが,prefabの2個目以降が入ってこない.タイミングの問題か,同じ名前だから1つ目以外は無視されているか.

(2)解決方法
いろいろ試したが,強引にやることに.

DefaultTrackableEventHandlerに以下を追加

public static bool meshVisi = false;

コード(抜粋)黄色の部分を追加

public class DefaultTrackableEventHandler : MonoBehaviour,
                                            ITrackableEventHandler
{
    #region PRIVATE_MEMBER_VARIABLES
 
    private TrackableBehaviour mTrackableBehaviour;
    
    #endregion // PRIVATE_MEMBER_VARIABLES



    #region UNTIY_MONOBEHAVIOUR_METHODS
	//
	public static bool meshVisi = false;
	/// 


    
    void Start()
    {

次に,同じくDefaultTrackableEventHandlerに以下を追加.(70行目前後にあり)

マーカーを発見したとき用 黄色の部分だけを追加

  private void OnTrackingFound()
    {
		meshVisi = true;//bird mesh renderer-on

        Renderer[] rendererComponents = GetComponentsInChildren<Renderer>(true);
        Collider[] colliderComponents = GetComponentsInChildren<Collider>(true);

 

マーカーを見失ったとき用(100行目くらい) 黄色の部分だけを追加

    private void OnTrackingLost()
    {
        Renderer[] rendererComponents = GetComponentsInChildren<Renderer>(true);
        Collider[] colliderComponents = GetComponentsInChildren<Collider>(true);

		meshVisi = false;//bird mesh renderer-off

 

(3)プレファブのメッシュに追加するスクリプト

using UnityEngine;
using System.Collections;

public class renderVisi : MonoBehaviour {
	
	void Start () {
		renderer.enabled = false;

	}

	void Update () {
		if(DefaultTrackableEventHandler.meshVisi == true)
			renderer.enabled = true;
		if(DefaultTrackableEventHandler.meshVisi == false)
			renderer.enabled = false;

	}
}

これを renderVisiというc#で保存し,プレファブのメッシュにアサイン

 

(4)やってみる。

 

(5)

実行順とかでもクリアできそうな強引なスクリプトが目立ちますが,,ご容赦.

納期が近いので、、