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

UGUI基本(1)

Colliderのつづきです.今回はUIを表示します.

 

  1. メニューバー>GameObject>UI>Text を選択します
  2. HierarchyにCanvasとTextが追加されましたunity3
  3. CanvasはUnityのUI用の入れ物です.他のUi要素はこのCanvas下に入れます.複数のCanvasを設置することも可能ですが,特段の事情が無い限り1つにしておいてください
  4. Hierarchyからcanvasを選択し,Canvas Scaler(無ければメニューバー>Component>Canvas Scaler で追加),Reference ResolutionのXを1920,Yを1200にするunityi2
  5. Reference Pixel Per Unitを100に(画像は233になっていますが気にしない)
  6. Textの名前を変更します.この例ではcounthyoujiにし,RectTransform Anchor Presetを左上固定(下画像と同じに)にし,Posxを360,PosYを-100,Widthを600に,Heightを120にしますunityui
  7. 前回のスクリプトを以下に変更します.黄色い部分が変更箇所です
  8. using UnityEngine;
    using System.Collections;
    
    //use for UI
    using UnityEngine.UI;
    
    public class hitcheck : MonoBehaviour {
    
    	//variable
    	int countInt = 0;  //
    	public Text myText; //use for UI text
    
    
    	void Start(){
    		myText.text = "0";
    	}
    
    
    	void OnTriggerEnter(Collider mycollider) {
    		Destroy(mycollider.gameObject);
    
    
    		//sound
    
    		//effect
    
    		//add point
    		countInt++;
    		myText.text = countInt.ToString ();
    	}
    
    }
  9. 注意する必要があるのは,「数字(int)」と「文字列(string)」の扱いです.UIには数字を表示させることができませんので,29行目の.ToString()で数字を文字に変換しています
  10. スクリプトの説明は以下のとおりscriptsetumei
  11. 実行動画です,スタートすると数値が初期化されゼロになり,Cubeが当たると数字が1増えます

    おつかれさまでした

Collider基本(4)

PlayMakerをつかって,お掃除ゲームを作ってみましょう.

まずはCubeが当たると消えるプログラム.これはさきほどのと一緒.

つぎに,マウスの座標を検出し,マウスをクリックしている間は常にそのX,Z座標でYは1固定で移動させなさい.と設定.

マウスを放したら,離した位置で高さ3に戻します

そして,ランダム座標を生成し,ボールを作成.変数に1を足して,それが30より多いか少ないか比較させ少ないともう1回ボールを作成し,変数に1足す.多いと何もないところへ遷移しアクションがないのでなにも動作しない.

そんなプログラムです.

マウスをクリックするとCubeが低くなり,マウスを放すとCubeの位置が高くなります.

Collider 基本(2)

その2

何かが当たって消えるというものです.

上のCubeの設定はTriggerON,Hitcheckのスクリプトがアサインされています.

ボールにはRigidbodyの設定がされています.

このCubeをボールに当てると,ボールが消えます.Game実行画面ではCubeを動かせませんが,Scenes画面では動かせますのでコントロールした代わりに直接動かしてみます.

「何かを叩くと消える」を実装するのであれば,これで可能です.

また,OnTriggerEnterに,音を再生する命令など与えると音が,爆発するオブジェクトを生成するなどすると爆発します.

 

Collider 基本(1)

Colliderとは

Colliderは衝突判定のための形状をさします.Unity内で作成したオブジェクトには全てこのColliderがついています.

Cubeで作った坂に,Physicsを入れた球を落とすと,動画のように壁に当たります.壁のColliderを一時的にオフにするとすり抜けてしまいます.

このColliderは衝突判定にも使われます.

Asset内の適当なところで,右クリックしCreate>C#Script でC#を作成し,hitcheckという名前に変更し全文を以下のスクリプトを変更します.

using UnityEngine;
using System.Collections;

public class hitcheck : MonoBehaviour {

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

	void OnTriggerEnter(Collider mycollider) {
		Destroy(mycollider.gameObject);
	}
}

このスクリプトは,Triggerにチェックを入れているオブジェクトにアサインします.

今回は壁にTriggerの設定を入れ(下の動画の46秒くらい),ボールが持っているRigidbodyに当たるとOnTriggerEnterの関数が実行されます.Triggerに当たったオブジェクトはOnTriggerEnterの変数mycolliderに格納され,Destroyで消去されます.

 

c#のファイル名を間違ったとき

プログラミングは独学なので,他の一般的なプログラミングの話とは異なるかもしれませんが,,,

Unityでc#のファイルを作成したとき,うっかりファイル名を変え忘れたり,ファイル名を変えたのに動かないときがあります.

それには,ここを修正してください.

public class qwatch : MonoBehaviour {

この qwatchがファイル名と同じなら動作します.そうでない場合はエラーがでます.

例えば,neko.csというファイルをinu.csと変更したいとき,

public class neko : MonoBehaviour {

となっているのを

public class inu : MonoBehaviour {

と変えればいいわけです.

ところで,うしろの{ から 一番下の行の }までがプログラムの中身になります.

using UnityEngine;
using System.Collections;
using System;

public class inu : MonoBehaviour {

	// Use this for initialization
	void Start () {
	
	}

	void Awake(){

		//StartCoroutine ("colorSwitch");
	}

}

黄色で示した5行目から17行目の間が,このinu.csで動作するプログラムです.なので,プログラムはこの{と}の間に書きましょう.

スクリプト事例ークイズ中の経過時間表示

staticで変数をグローバル化しているけど,これは使用したのか不明.

lapTimeのboolをOn/Offしてて,ポーズ中は時間経過をスルー if(false) させている.

ポーズ中は色を点滅= コルーチンのcolorSwitch()のとこ

これ,colorSwitch()のコルーチンを止めていないっぽいんで,7問だからいいけど,ポーズ以外はコルーチン止めたほうがいいかも.

using UnityEngine;
using System.Collections;
using System;
using UnityEngine.UI;


public class qwach : MonoBehaviour {

	public static float Quiztime = 0;//read from global
	public GameObject startPanel;
	public GameObject startKaitou;

	public Text timeTex; //Text用変数
	private bool lapTime;


	// Use this for initialization
	void Start () {
		Quiztime = 0f;
		startPanel.SetActive (true);
		lapTime = false;
		timeTex.color = Color.grey;
	}

	void Awake(){

		//StartCoroutine ("colorSwitch");
	}

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

		if (lapTime) {
			Quiztime += Time.deltaTime;
			timeTex.text = Quiztime.ToString ("f2") + "秒経過";
			;
			//timeTex.text = timeTex + "秒経過";
			//Debug.Log (time.ToString ());
		} else {
			//pause syori
			//StartCoroutine("colorSwitch");
				
			}
	
	}

	private IEnumerator colorSwitch(){
		while (true) {
	
				timeTex.color = Color.grey;
				yield return new WaitForSeconds (0.5f);
				timeTex.color = Color.white;
				yield return new WaitForSeconds (0.5f);
		}
	}


	public void qwPause(){
		StartCoroutine ("colorSwitch");
		lapTime = false;
	}

	public void qwStart(){
		StopCoroutine ("colorSwitch");
		timeTex.color = Color.white;
		lapTime = true;
	}


	public void qStart(){
		lapTime = true;
		startPanel.SetActive (false);
		timeTex.color = Color.white;

		startKaitou.SetActive (true);
	}

}

 

トグルボタンをON/OFFでHaloを出す

Haloはライトオブジェクトにあてるとぼうっと光った雰囲気を出せます.(component>effectにはいっています)

トグルボタンを押した感を出すためにHaloをON/OFF表示させるためのスクリプトです

 

using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public class btnshowHalo : MonoBehaviour {
	public GameObject lightHalo;//assign activate object

	public Toggle toggleBtn;//for assign toggle btn

	// Use this for initialization
	void Start () {
		lightHalo.SetActive(false);//initialize
	}
	
	// Update is called once per frame
	void Update () {
	
	}


	public void showHalo(){

		if (toggleBtn.isOn) {
			lightHalo.SetActive (true); //show halo
		} else {
			lightHalo.SetActive (false); //hide halo
		}
	}
}

アサインすると,トグルボタンとアクティベートするゲームオブジェクトをエディタでアサインします.ボタン押された時のスクリプト設定をやって完了

ntpサーバを使って,デバイス間の時刻修正

カウントダウンアプリをつくっていますが,各自のスマホの時間がバラバラなので,ntpから差分とった時刻で正確な時間を出すようにしてみました.

修正中ですが,概ねこれで作動します.

元ネタはこれ→ http://ftvoid.com/blog/post/847

HTML5ならもう少し簡単だったのですが,,

using UnityEngine;
using System;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Threading;

using UnityEngine.UI;//use unity gui

// NTP同期時刻を管理するクラス
public class NtpDate : MonoBehaviour {
	private DateTime ntpDate;   // NTP同期時刻
	private float rcvAppDate;   // NTP通信時のアプリ時刻

	private IPEndPoint ipAny;
	private UdpClient sock;
	private Thread thread;
	private volatile bool threadRunning = false;
	private byte[] rcvData;

	public string myString; //for time display
	private DateTime endDate; //for end date
	public Transform myButton; //get button object
	public Text countText; //Text用変数
	private TimeSpan zure; 

	// 初期化
	void Start() {
		// リクエスト実行
		SyncDate();
		// 時刻表示(デバッグ用)
		StartCoroutine(ShowSyncDate());

		//Debug.Log (System.DateTime.Now);
	}

	// 同期時刻の表示
	private IEnumerator ShowSyncDate() {
		while ( true ) {
			yield return new WaitForSeconds(0.1f);//0.5f

			timeCheck ();// do timeCheck() every 1 second

			//if ( Date == false ) {
			if ( Date == null ) {
				Debug.Log("Time is not received.");
			} else {
			//Debug.Log("Receive date : " + Date.ToString());
				//	Debug.Log (DateTime.Now);//  DateTime.Now is confiured time
			}
		}
	}


	/// for GUI my add
	public void timeCheck(){

	endDate = new DateTime(2016, 4, 2, 18,30,00); //本番用

	//	endDate = new DateTime(2016, 2, 4, 12,30,00);//for test
		TimeSpan sabun = endDate - DateTime.Now; //compare now time and end time

//		Debug.Log ("before" + sabun);
//		Debug.Log ("after" + (sabun - zure));


		//int result = TimeSpan.Compare(endDate, DateTime.Now);// cant use
		sabun = sabun - zure;//zure naosu
		if (sabun.Days <= 0 && sabun.Hours <= 0 && sabun.Minutes <= 0 && sabun.Seconds <= 0) { //sabun is all zero and minus
			myString = "Light It Up Blue!"; //message of button
			countText.text = myString; //put text to GUItext
			myButton.GetComponent<Toggle>().interactable = true; //unlock the button
		} else {
			myString = string.Format ("{0:00}D{1:00}H{2:00}M{3:00}S", sabun.Days, sabun.Hours, sabun.Minutes, sabun.Seconds);//string format
			countText.text = myString; //time remaining
			myButton.GetComponent<Toggle>().interactable = false; //lock button before last time
		}



	}

	public void Update(){
	//	timeCheck ();

	}


	// アプリケーション終了時処理
	void OnApplicationQuit() {
		if ( thread != null ) {
			thread.Abort();
		}
		if ( sock != null ) {
			sock.Close();
		}
	}



	// 時刻同期を行う
	public void SyncDate() {
		// リクエスト実行
		threadRunning = true;
		thread = new Thread(new ThreadStart(Request));
		thread.Start();

		// リクエスト待機コルーチン実行
		StartCoroutine(WaitForRequest());

		Debug.Log("Thread is started.");
	}

	// NTPサーバに対してリクエストを実行する
	private void Request() {
		// ソケットを開く
		ipAny = new IPEndPoint(IPAddress.Any, 123);
	//	sock = new UdpClient(ipAny);
		sock = new UdpClient();

		// リクエスト送信
		byte[] sndData = new byte[48];
		sndData[0] = 0xB;
		sock.Send(sndData, sndData.Length, "ntp.jst.mfeed.ad.jp", 123);

		// データ受信
		rcvData = sock.Receive(ref ipAny);
		// 実行中フラグクリア
		threadRunning = false;
	}

	// リクエスト待機コルーチン
	private IEnumerator WaitForRequest() {
		// リクエスト終了まで待機
		while ( threadRunning ) {
			yield return 0;
		}

		// アプリ時刻保存
		rcvAppDate = Time.realtimeSinceStartup;
		Debug.Log (rcvAppDate);
		// 受信したバイナリデータをDateTime型に変換
		ntpDate = new DateTime(1900, 1, 1);
		var high = (double)BitConverter.ToUInt32(new byte[] { rcvData[43], rcvData[42], rcvData[41], rcvData[40] }, 0);
		var low = (double)BitConverter.ToUInt32(new byte[] { rcvData[47], rcvData[46], rcvData[45], rcvData[44] }, 0);
		ntpDate = ntpDate.AddSeconds(high + low / UInt32.MaxValue);

		// UTC→ローカル日時に変換
		ntpDate = ntpDate.ToLocalTime();
		zure = Date - DateTime.Now;
			Debug.Log ("zure" + zure);
	}

	// NTP同期時刻
	public DateTime Date {
		get {
			
			return ntpDate.AddSeconds(Time.realtimeSinceStartup - rcvAppDate);
		}
	}
}

 

photon 特定名のルームを作成するかそこに入室する

どうしても同じルームに入り,customRoomPropertiesを取得して,同じルームに入室している人全員に同じ設定を与えたかったので.

(1)まずルーム作成のスクリプト

これは空のゲームオブジェクトに当てる

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

public class photonsystem : Photon.MonoBehaviour {
	public string objectName;//use for photon instantiate
	private bool connectFailed = false; //use for network status check

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

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


	//call when room list upadate "must use"
	void OnReceivedRoomListUpdate(){
		CreateRoom ();
	}


	/////create room with custom room options

	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", "blue"}};
		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 {
				//room name matched
				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);
	}

	}

 

(2)そのカスタムプロパティを呼び出すスクリプト

これをライトにアサインしています

using UnityEngine;
using System.Collections;
using Hashtable = ExitGames.Client.Photon.Hashtable;
using UnityEngine.UI;

public class cpLight : MonoBehaviour {
	public Light lightObj2;
	private string cpstring = "red";

	// Use this for initialization
	void Start () {
		lightObj2 = GetComponent<Light>();
	}
	
	// Update is called once per frame
	void Update () {

	
	}


	//cp changed is here
	void OnPhotonCustomRoomPropertiesChanged(){
	
		if (PhotonNetwork.inRoom) {// ルームの状態を取得
			Room room = PhotonNetwork.room;
			if (room == null) {
				return;
			} else {
				Hashtable cp = room.customProperties;
				//cpstring = (string)cp ["r"];
				cpstring = (string)cp ["r"];
				//Debug.Log (cp ["r"]);
				if (cpstring == "blue") {
					lightObj2.color = Color.blue;
					//GetComponent<Light>.color = Color.blue;
				}
				if (cpstring == "red") {
					lightObj2.color = Color.red;
					//GetComponent<Light>.color = Color.blue;
				}
				if (cpstring == "green") {
					lightObj2.color = Color.green;
					//GetComponent<Light>.color = Color.blue;
				}
			}
		}
	
	}


}

 

(3)テスト用にボタンを作成し,そのボタンにあてるスクリプトです

using UnityEngine;
using System.Collections;
using Hashtable = ExitGames.Client.Photon.Hashtable;

public class lightColor : Photon.MonoBehaviour {

	public Light lightObj;

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


	//	if (!photonView.isMine) {
			//transform.position = Vector3.Lerp(transform.position, this.correctPlayerPos, Time.deltaTime * 5);
			//transform.rotation = Quaternion.Lerp(transform.rotation, this.correctPlayerRot, Time.deltaTime * 5);


	//	}
	
	}

	public void colorRed(){
		//lightObj.color = Color.red;
	ExitGames.Client.Photon.Hashtable h = new ExitGames.Client.Photon.Hashtable() { { "r", "red" } };
	PhotonNetwork.room.SetCustomProperties(h);

	}


	public void colorGreen(){
	//	lightObj.color = Color.green;
		ExitGames.Client.Photon.Hashtable h = new ExitGames.Client.Photon.Hashtable() { { "r", "green" } };
		PhotonNetwork.room.SetCustomProperties(h);
	}

	public void colorBlue(){

		ExitGames.Client.Photon.Hashtable h = new ExitGames.Client.Photon.Hashtable() { { "r", "blue" } };
		PhotonNetwork.room.SetCustomProperties(h);
	//	lightObj.color = Color.blue;
	}

}

これで,ボタンをクリックすると

photon2

このアプリの画面は全て同じ色になります.タイムラグは1秒以内くらいです

 

Photon一覧

テラシュールブログさんありがとう!

カスタムプロパティを変えたときに呼ばれるがこれ

void OnPhotonCustomRoomPropertiesChanged(){ }

ちなみにupdateでカスタムプロパティ呼ぶとたぶん2回目でエラーでる(未検証).どうも別の所にスクリプトがアサインされてたっぽい.

なので,onChangeが必要だったのですが,onChangeで検索しても出てこず,まさかChangedだったとは,,,

 

参照先