RandamNumberゲームの作成


簡単なゲーム作成を通して、uGUI,Http通信、Jsonパースを学習する。今回は後編。(前編はこちら)WebAPIにアクセスしてランキングを表示する。

WebAPIの確認

1.JSP&Servletの20で作成したローカルなWebAPIに以下のようなURLでリクエストを投げると
http://localhost:8080/ScoreAPI/GetRanking?name=mjpurin&score=32000&sex=0&count=100
下のようなJSONが返却される。

これはリクエストの際にname,score,sex,countをパラメーターとして渡すとそのデータをデータベースに挿入し、その挿入データのidと何位だったのかを表すRank,ランキングに入ったのかというbool,それと合わせて実際のランクングデータを配列で返却するものだ。このAPIを利用してランキングをつくる。
2.Sendボタンを押した時にWebAPIにアクセスすれば良さそうだ。CanvasController.csを以下のように作成しCanvasにアタッチする。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Linq;
using System;
using UnityEngine.Networking;



public class CanvasController : MonoBehaviour {
	private const int COUNT=100;//ベスト100の取得
	private const float CELLHEIGHT = 65.0f;//セル一つ分の高さ
	public Text name;//ユーザーが入力した名前が入るTextオブジェクト
	public Text score;//ユーザーが入力した点数が入るTextオブジェクト
	public ToggleGroup tg;
	public GameObject startButton;
	public GameObject formPanel;
	public GameObject rankingPanel;
	public GameObject cells;
	public GameObject prefab;
	public Sprite[] sprites;

	//Sendボタンが押された時の処理
	public void OnSendClick(){
		StartCoroutine (PostConnect ());
	}
	//コルーチンでWebに接続する。
	IEnumerator PostConnect(){
		//選択されているラジオボタンを取得(usingにSysatem.Linqが必須)
		Toggle tgl = tg.ActiveToggles ().FirstOrDefault();
		//パラメーターを詰める
		WWWForm form = new WWWForm();
		form.AddField("name", name.text);
		form.AddField("score", score.text);
		form.AddField("sex", tgl.name=="Man"? 0:1);
		form.AddField ("count", COUNT);
		string url="http://localhost:8080/ScoreAPI/GetRanking";
		//Postで通信
		UnityWebRequest uwr = UnityWebRequest.Post (url,form);
		yield return uwr.SendWebRequest ();
		if(uwr.isNetworkError){
			Debug.Log (uwr.error);
		}else{
			//Unity標準のJSONパーサーをつかう。JSON文字列を元にクラスを作成する。
			var ranking = JsonUtility.FromJson<RankingData>(uwr.downloadHandler.text);
			//ランキングい入った時の処理
			if (ranking.isRankingIn) {
				//ランキングの数だけ回す
				for(int i=0;i<ranking.list.Count;i++){
					//cellをInstantiate
					GameObject cell = Instantiate (prefab);
					//自分のデータだったら背景を青にする
					if (ranking.lastId == ranking.list[i].id) {
						Image panel = cell.GetComponent<Image> ();
						panel.color = Color.cyan;
					}
					//cellをCellsの子要素にする。
					cell.transform.SetParent (cells.transform, false);

					//cellの子要素Rankを取得
					Text rank = cell.transform.Find("Rank").GetComponent<Text> ();
					//順位を表示
					rank.text = (i+1).ToString ();
					//性別に応じてアイコンを表示
					Image image = cell.transform.Find("Thumb").GetComponent<Image> ();
					image.sprite = ranking.list[i].sex == 0 ? sprites [0] : sprites [1];
					//名前を表示
					Text name = cell.transform.Find("Name").GetComponent<Text> ();
					name.text = ranking.list[i].name;
					//点数を表示
					Text scoreText = cell.transform.Find("Score").GetComponent<Text> ();
					scoreText.text = ranking.list[i].score .ToString();

				}

				rankingPanel.SetActive (true);
//表示位置にスクロールさせる

				if (ranking.rank > Screen.height/CELLHEIGHT) {


					Vector3 vec = cells.transform.localPosition;

					float distination = 
						ranking.rank * CELLHEIGHT - Mathf.Max(Screen.height / 2,Screen.height - (ranking.list.Count - ranking.rank) * CELLHEIGHT);
					float diff = distination-vec.y;
					while(diff>	0.1f){
						vec = cells.transform.localPosition;
						vec.y = Mathf.Lerp (vec.y, distination, 0.1f);
						cells.transform.localPosition = vec;
						diff = distination - vec.y;
						yield return new WaitForSeconds (0.01f);

					}

				}

			}
			formPanel.SetActive (false);
			startButton.SetActive (true);

		}

	}
}

//Jsonパースの為にクラスを作成する
[Serializable]
class RankingData{
	public int lastId;
	public int rank;
	public List<Score> list;
	public bool isRankingIn;

}
[Serializable]
class Score{
	public int id;
	public string name;
	public int score;
	public int sex;
}



3.インスペクターからpublicフィールドを以下のように登録する。

4.ヒエラルキーからSubmitButtonを選択してインスペクターから以下のようにOnClickを登録する。

5.最初はFormPanelもRankingPanelも非表示にしておこう。それぞれを選択し、Activeのチェックを外しておこう。

6.Gameの進行に合わせてPanelのActiveを切り替えたい。CubeController.csに以下のように追記しよう。

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

public class CubeController : MonoBehaviour {
	public Text Score;
	public GameObject startButton;
	private Coroutine game;
	private bool  isPlay;
	/******追加*****/
	public GameObject formPanel;
	public GameObject RankingPanel;
	/***************/
	void Update () {

		if(isPlay && Input.GetMouseButtonDown(0)){
			RaycastHit hit;
			Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
			if(Physics.Raycast(ray,out hit,100.0f)){
				if(hit.collider.name=="Cube"){
					StopCoroutine (game);
					isPlay = false;
					/******追加*****/
					formPanel.SetActive (true);
					/***************/
				}
			}
		}
	}
	IEnumerator RandomNum(){
		while (true) {
			transform.Rotate (0, 10.0f, 0);
			yield return new WaitForSeconds (0.3f);
			Score.text = Random.Range (0, 100000).ToString();
		}
	}
	public void StartClick(){

		game=StartCoroutine (RandomNum ());
		startButton.SetActive (false);
		isPlay = true;
		/******追加*****/
		//古いランキングデータは削除
		Transform cells = RankingPanel.transform.FindChild ("Cells");
		for( int i=0; i < cells.childCount; i++ ){
			GameObject.Destroy( cells.GetChild( i ).gameObject );
		}
		//スクロールを先頭に戻す
		Vector3 vec = cells.localPosition;
		vec.y = 0f;
		cells.localPosition = vec;
		//非表示
		RankingPanel.SetActive (false);
		/***************/

	}

}

7.Cubeのインスペクターからpublicフィールドを以下のように登録する。

確認

8.実行してみよう。ランクインした時にランキングが表示されれば成功だ。