ぼくの息抜き

ぼくの息抜き

気ままな二人が記事を書くことで息抜きしていくブログ

CSS MenuMaker

unityゲームプログラミング 雨を降らすゲームを作るPart10 -放置ゲームの転生を導入3-

f:id:bokunoikinuki:20180621201305p:plain

なかなか放置ゲームの転生要素を実装するには時間がかかる。

アップグレードのSceneをGameSceneとは切り離された別のもので作っているので、よく考えたら今後多種多様な放置ゲームを作るとなってもUIなどを変えてしまえばそのまんま流用できる。

むちゃくちゃ簡単に放置ゲームが量産できるということだ。

という大きな期待を胸に転生要素を作り上げていく。転生要素Part3。

アップグレード画面を完成させる

前回の記事で残りのアップグレード画面を実装するにあたって必要な手順を書き出した。

  • 新しいアップグレードSceneの簡易デザイン作り
  • GameSceneから転生ボタンでアップグレードSceneに遷移できるように
  • アップグレードSceneからGameSceneに遷移できるように
  • 転生時ポイントも追加されるように
  • アップグレードのスクロール実装
  • スクロール画面からParticle Systemの数値いじれるように実装
  • いじれる数値をたくさん増やす
  • デザインを整える
  • 完成!

スクロールまでは順調に実装できたが、次の

『スクロール画面からParticle Systemの数値いじれるように実装』

が厄介だ。

この手順をより詳細に分解すると

  • Prefabを複製する
  • 複製時にそれぞれ別の要素を割り振る
    ⇨割り振る要素は
     ⇨Particle Systemの数値
     ⇨アップデート内容
     ⇨現状のレベル
     ⇨能力Upの経験値テーブル

これらをPrefab生成時に全て割り振れるようにしなくてはならない。

自分の今の能力だと一つ一つユニークなPrefabを作る方が早く実装できるだろう。

成長のために頑張るか、とりあえず作れることを試すか。

悩ましい。

少し考えてみたら案外楽にできるかもしれない。

f:id:bokunoikinuki:20180701125657j:plain

  • Prefab側で使う似たような数値を洗い出す
  • Prefab側で必要な変数と関数を作る
  • UpgradeManagerでそれぞれ組み込む

この手順でやればいいと思うけど、そもそもPrefab一つですらParticle Systemの数値の変え方がわからん。

ということでまずは一つのPraticle Systemの数値を変更できるかというところから始めよう。

まずは一つのParticle Systemの数値をアップグレード画面から変える

f:id:bokunoikinuki:20180701141441j:plain

わかりやすいようにParticle Systemの変更する数字は StartSizeにする。

ps.main.startSize = float;

で変えられるようだ。ということでfloat型で変数を作る。

Unity - Scripting API: ParticleSystem.MainModule.startSize

public static floatをupgaradeManagerに作って、ParticleSystemのscriptから起動時に読み込むことで無事StartSizeが変わった。

ボタンが反応しない

スクロールの中のボタンが反応しない。

【Unity】ボタンが押せない!チェックすべき7つのポイント

色々記事を探したが、どれも違う。

スクロール特有か?

よーーーく見直して、全てのRaycast外したら押せた。

いやー、毎回ボタンはややこしい。他の記事でも書いてあるけど、デフォルトでRaycast Target のチェック外してくれればいいのに。Imageだけではなく、Textも要注意。且つ、親要素だけでなく同じ階層にある要素もきちんとみなくてはいけない。

f:id:bokunoikinuki:20180701154130p:plain

今回はUpgradeUpButtonを押そうとして、同じ階層のText群に阻まれていた。いやー、やられた。

しかし、これで一つのParticle Systemの数字をUpgradeSceneから変えることができた。

大きな一歩だ。

Prefabのscriptはどうするべきか

Particle Systemの一つだけ変えられるようになった。

using UnityEngine.UI;

public class UpgradePartManager : MonoBehaviour {



	// Use this for initialization
	void Start () {
		Button upgradeUpButton = this.gameObject.transform.Find ("UpgradeUpButton").GetComponent<Button> ();
		Debug.Log (upgradeUpButton);
		upgradeUpButton.onClick.AddListener (UpStartSize);
		
	}
	
	// Update is called once per frame
	void Update () {
		
	}

	void UpStartSize () {
		UpgradeManager.startSize += 1.0f;		
	}
}

 

シンプルに一つだけ書いてあるが、Prefabに紐づいてるこのscriptを複製したら、全てのボタンがstartSizeが上がってしまう。

これをPrefabを複製する際にここに要素を決めていく必要がある。

先にもう少ししっかりアップグレードのスクリプトを記述する。

  • 今プラスボタンしか反応しない。マイナスボタンも紐づける。
  • テキスト各種紐づける。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

using UnityEngine.UI;

public class UpgradePartManager : MonoBehaviour {

	Text currentLevelText;
	Text needPointText;
	float needPoint;

	// Use this for initialization
	void Start () {
		Button upgradeUpButton = this.gameObject.transform.Find ("UpgradeUpButton").GetComponent<Button> ();
		upgradeUpButton.onClick.AddListener (Upgrade);

		Button upgradeDownButton = this.gameObject.transform.Find ("UpgradeDownButton").GetComponent<Button> ();
		upgradeDownButton.onClick.AddListener (Downgrade);

		Text upgradeContentText = this.gameObject.transform.Find ("UpgradeContentText").GetComponent<Text> ();
		upgradeContentText.text = "雨粒の大きさ";

		currentLevelText = this.gameObject.transform.Find ("CurrentLevelText").GetComponent<Text> ();

		needPointText = this.gameObject.transform.Find ("NeedPointText").GetComponent<Text> ();


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

	void Upgrade () {
		UpgradeManager.startSize += 0.1f;	
		RefleshText();
	}

	void Downgrade () {
		UpgradeManager.startSize -= 0.1f;
		RefleshText();
	}

	void RefleshText () {
		needPoint = UpgradeManager.startSize * 20;
		needPointText.text = "必要ポイント: " + needPoint.ToString ("f0");
		currentLevelText.text = "現在のレベル: " + UpgradeManager.startSize;
	}
}

ボタン2つにテキスト3つ紐付けた。

そうして問題点が見えてきた。startSizeは最初の大きさが0.1fだが、emissionは10だったりする。

いや、これ書いてて思ったが、defaultの数値を変数に入れて、

defaultNum * currentLevel

みたいな形にすればいいのか。fmfm。

とするとstartSizeやemissionのcurrentLevelだけpublic static intにして、Particle Systemのスクリプトで再度計算させてやればいいな。

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

using UnityEngine.UI;

public class UpgradePartManager : MonoBehaviour {

	Text currentLevelText;
	Text needPointText;
	int needPoint;

	// Use this for initialization
	void Start () {
		Button upgradeUpButton = this.gameObject.transform.Find ("UpgradeUpButton").GetComponent<Button> ();
		upgradeUpButton.onClick.AddListener (Upgrade);

		Button upgradeDownButton = this.gameObject.transform.Find ("UpgradeDownButton").GetComponent<Button> ();
		upgradeDownButton.onClick.AddListener (Downgrade);

		Text upgradeContentText = this.gameObject.transform.Find ("UpgradeContentText").GetComponent<Text> ();
		upgradeContentText.text = "雨粒の大きさ";

		currentLevelText = this.gameObject.transform.Find ("CurrentLevelText").GetComponent<Text> ();

		needPointText = this.gameObject.transform.Find ("NeedPointText").GetComponent<Text> ();


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

	void Upgrade () {
		UpgradeManager.startSizeLevel += 1;	
		RefleshText();
	}

	void Downgrade () {
		UpgradeManager.startSizeLevel -= 1;
		RefleshText();
	}

	void RefleshText () {
		needPoint = UpgradeManager.startSizeLevel * 2;
		needPointText.text = "必要ポイント: " + needPoint.ToString ("f0");
		currentLevelText.text = "現在のレベル: " + UpgradeManager.startSizeLevel;
	}
}

少し変えたが、UpgradeManager.startSizeLevelというpublic static変数がユニークな数字になってしまっているので、これも変数を追加してPrefab生成時に代入するようにする。

 

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

using UnityEngine.UI;

public class UpgradePartManager : MonoBehaviour {

	Text currentLevelText;
	Text needPointText;
	int needPoint;
	int currentLevel;
	string contentText;

	// Use this for initialization
	void Start () {
		contentText = "雨粒の大きさ";
		currentLevel = UpgradeManager.startSizeLevel;


		Button upgradeUpButton = this.gameObject.transform.Find ("UpgradeUpButton").GetComponent<Button> ();
		upgradeUpButton.onClick.AddListener (Upgrade);

		Button upgradeDownButton = this.gameObject.transform.Find ("UpgradeDownButton").GetComponent<Button> ();
		upgradeDownButton.onClick.AddListener (Downgrade);

		Text upgradeContentText = this.gameObject.transform.Find ("UpgradeContentText").GetComponent<Text> ();
		upgradeContentText.text = contentText;

		currentLevelText = this.gameObject.transform.Find ("CurrentLevelText").GetComponent<Text> ();

		needPointText = this.gameObject.transform.Find ("NeedPointText").GetComponent<Text> ();


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

	void Upgrade () {
		currentLevel += 1;	
		RefleshText();
	}

	void Downgrade () {
		currentLevel -= 1;
		RefleshText();
	}

	void RefleshText () {
		needPoint = currentLevel * 2;
		needPointText.text = "必要ポイント: " + needPoint.ToString ("f0");
		currentLevelText.text = "現在のレベル: " + currentLevel;
	}
}

 ユニークな変数は無くした。

でわかったことはstring変数とint変数それぞれ一つずつ代入できれば、Prefab別に別々のアップグレードができそうということだ。

それでは実際にPrefabを複製してみる。

Prefabを生成して別々のアップグレードできるように

山場といった感じだ。これ終えたらあとはデザインとどんな数字をアップグレードとするかの楽しい作業+ゲームバランス調整でゲームが完成する。

あとタイトルか。

ワクワクしてきたー!

まずは一つ生成。

予想通りできすぎて拍子抜け。

ここから配列でそれぞれ指定して、for文で配列文だけPrefabを生成できれば完成だ。

using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class UpgradeManager : MonoBehaviour {

	public static int upgradePoint = 0;
	public static int startSizeLevel = 1; 
	string startSizeText = "雨粒の大きさ";

	// Use this for initialization
	void Start () {
		Button gameStartButton = GameObject.Find ("GameStartButton").GetComponent<Button> ();
		gameStartButton.onClick.AddListener (LoadGameScene);

		Text upgradePointText = GameObject.Find ("UpgradePointText").GetComponent<Text> ();
		upgradePointText.text = "残り振り分けポイントは\n" + upgradePoint;

		GameObject content = GameObject.Find ("Content");

		GameObject upgradePartBack = Resources.Load<GameObject> ("Prefabs/UpgradePartBack");
		GameObject pf = Instantiate<GameObject> (upgradePartBack);
		pf.transform.SetParent (content.transform, false);
		UpgradePartManager manager = pf.GetComponent<UpgradePartManager> ();
		manager.Set(startSizeLevel, startSizeText);

		
	}

	void LoadGameScene () {
		SceneManager.LoadScene ("GameScene");
		print ("a");
	}
}

 盲点だった。アップグレードのcurrentLevelが変更できても最後にcurrentLevelに数値を反映させないとゲームに反映されない。

これはどうやったらいいんだ?

一つだけだったら戻り値ありの関数を作って入れ直せばいいんだが 。

ユニークな番号振って、その配列の番号に数字を戻す関数を作ればいいのか。

dictionary型を使ってみようと思う。

いや、色々調べたら素直に配列が良さそうだ。

ひえー、できたー。

f:id:bokunoikinuki:20180701173906p:plain

 

次はいじれる数値をたくさん増やす。

どんどん追加していこう!

あとは

  • アプリを閉じていても、RPが貯まるように
  • タイトル作る

 

メモ書き

アップグレード追加するときはUpgradeManagerとUpgradePartManagerを変える。