CanvasのHpbarの特定の位置にInstantiateしよう

#概要
「barの端に合わせてInstantiate」ですが、一見簡単に見えますよね。しかし、canvas内に正確な位置に生成するのって実は一工夫いるんです。
![スクリーンショット (39).png](https://qiita-image-store.s3.amazonaws.com/0/244066/9a9445be-331a-96b1-321e-326970aa1f2b.png)
今回紹介するにあたって、私が作ったゲームの画面で解説致します。
上の画面の下部にbarがありますよね。ここではplayerのエネルギー残量を表しています。浮いている泡を取ることで増加、魚にぶつかることで減少するようになっており、その増減を、ぶつかった瞬間からパッとbarの右端に表示するような仕組みになっています。
こんな感じですね。![スクリーンショット (30).png](https://qiita-image-store.s3.amazonaws.com/0/244066/2cb05802-f494-cba1-4510-c2b5d0340b41.png)
これはエネルギーがほとんど残っていないときです。
![スクリーンショット (29).png](https://qiita-image-store.s3.amazonaws.com/0/244066/197bb97a-1d9a-f4cb-d107-992f01a25f4c.png)
これはエネルギーが９０くらいある時です。
きちんと残量に合わせて表示される位置が変わっているのがお分かりでしょうか。

では、泡にぶつかったときに＋5が表示されるようにしましょう。
やることとしては、
　１．表示する画像をつくる
　２．energyをシングルトンにする
　３．barを作って長さにenergyを反映させる
　４．+5の表示　（ここがポイント！）
　５．泡に付けるスクリプトを書く
こんな感じですね。
さっそく実装に入ります。

#１．表示する画像を作る
イラレとかで表示したい画像を作ってCanvasにImageを作り、Prefabかしておきましょう。
![スクリーンショット (44).png](https://qiita-image-store.s3.amazonaws.com/0/244066/0d021dcb-5a77-f27c-e8e7-588196c892f6.png)




#２．energyをシングルトンにする
ここでは、まずenergyをシングルトンにして管理することにしています。
(次のステージでもenergyが引き継がれるようにしたいですよね！)
こんな感じです。

```c#:EventManager.cs
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;

//EventManagerをシングルトンにする
public class EventManager : SingletonMonoBehaviour<EventManager> {
	
//初期値を２０に設定
	public static float ene = 20;

//energyの書き込み
	public void setScore (float n){
		ene = n;
	}
//energyの取得
	public float getScore(){
		return ene;
	}
}

```
このスクリプトはEmptyGameObjectを作ってくっつけておきましょう。

#３．barを作って長さにenergyを反映させる
では、次にbarをEnergyBarという名前で作り(作り方は省略)、InspectorのWhole　Numbersのチェックをはずしておきます。
そしてHpControllerというスクリプトを作って一番上のEnergyBarにくつっけておきます。
このスクリプトがenergyの値の管理と、値が変更されたときにbarの長さを変更する指示を出してくれます。

```c#:HpController.cs
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class HpController : MonoBehaviour {

	EventManager eventManager;

	//Hpbar
//barのマックスの値を３００に設定
	private static float maxbarHp = 300f;
//energyをこのスクリプトではHpと呼ぶことにする
	private float Hp;
	private Slider HpSlider;

	void Start () {
//EventManagerからスコアを取得
		float Hp = EventManager.Instance.getScore ();
//barの中の位置を取得
		HpSlider = this.GetComponent<Slider>();
//barの最大の長さを１としているので、長さはHp/300ということになる
		HpSlider.value = (float)Hp/ (float)maxbarHp;
//EventManagerに値を返す(不要かも)
		EventManager.Instance.setScore (Hp);

	}


	// Update is called once per frame
	void Update () {
//EventManagerからスコアを取得
		float Hp = EventManager.Instance.getScore ();
		//エネルギー自動減少(私のゲームでの設定)
		Hp -= Time.deltaTime;

		EventManager.Instance.setScore (Hp);
//下の関数を実行(あとで使うのでとりあえず書いておく)
		UpdateHpValue ();
//energyがゼロになったらゲームオーバーシーンになる(私のゲームでの設定)
		if (Hp <= 0) {
			SceneManager.LoadScene (GameOver);
		}
	}

	//Hp表示用アップデート
	public void UpdateHpValue(){
		var Hp = EventManager.Instance.getScore ();
		HpSlider.value = (float)Hp / (float)maxbarHp;
```

#４．+5の表示
では、次に、泡にぶつかったとき、得点をどのように変更していきたいかを、同じスクリプトに書き加えていていきます。
ここで、barの右端の丸ぽちのedgepointというImageをつくって、energypoint という名前のテキストに、常に点数を表示させるようにしておくと便利です(edgepointはこの後使うので必ず用意！)
これをEnergyBarの最下層に入れておきましょう
![スクリーンショット (43)_LI.jpg](https://qiita-image-store.s3.amazonaws.com/0/244066/85277926-b68f-7d46-aa8f-e54fd2cd9976.jpeg)
そして、edgepointをbarの右端に表示するよう設定しておくのがポイント。
![スクリーンショット (46)_LI.jpg](https://qiita-image-store.s3.amazonaws.com/0/244066/ace00882-87ac-4d26-302c-419026ac5e8d.jpeg)



```c#:HpController.cs
	public GameObject edgepoint;

	//５ｐ泡を取った時
	public void EneUp5(){

//EventManagerからスコアを取得、５点追加
		var Hp = EventManager.Instance.getScore ();
		Hp += 5f;

//大事！！！
//パッと表示させたいImageを、edgepointの子としてInstantiate
		Image bubbleP5 = Instantiate(plus5, Vector3.zero, Quaternion.identity) as Image;		
		bubbleP5.transform.SetParent (edgepoint.transform, false);
//１．５秒後にDestroy。同時にtextも消去
		Text txt5 =bubbleP5.GetComponentInChildren<Text>();
		Destroy (bubbleP5, 1.5f);
		Destroy (txt5, 1.5f);
		bubbleP5 = null;
		txt5 = null;
//energyをEventManagerに返す
		EventManager.Instance.setScore (Hp);

	}

	//Hp表示用アップデート
	public void UpdateHpValue(){
		var Hp = EventManager.Instance.getScore ();
		HpSlider.value = (float)Hp / (float)maxbarHp;
		Text energycount = this.GetComponentInChildren<Text> ();
		energycount.text= Hp.ToString("f0");

```


#５．泡に付けるスクリプトを書く

最後に、泡につけるスクリプトを書きましょう。
もちろん、泡にColliderをつけておくことは忘れずに！

ここでは、泡にぶつかったとき、HpController.csを探し出して、対応する関数を実行するように指示を飛ばします。

```C#:BubbleScript.cs
using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public class BubbleScript : MonoBehaviour {
	private GameObject energybar;
	private HpController hpController;

	// Use this for initialization
	void Start () {
//barを見つける
		GameObject energybar = GameObject.Find ("EnergyBar");

//barに付けるスクリプトHpControllerを見つける
		hpController = energybar.GetComponentInChildren<HpController>();
	}

//Playerにぶつかったときの反応
    void OnTriggerEnter (Collider col){
        if (col.tag == "Player") {

//HpControllerに"Eneup"を実行するように指示
			hpController.SendMessage ("EneUp5");
//HpControllerに"UpdateHpValue"を実行するように指示
			hpController.SendMessage("UpdateHpValue");

//ぶつかった泡(このスクリプトがついているgameobject)をDestroyする		
			Destroy(this.gameObject);
		}
	}
}
```

いかがですか。できましたでしょうか。
今回は、barの端にしましたが、Canvasの子として設定し、座標を入れてあげれば、自由な位置にInstantiateすることができますよ！