無理を通して道理を蹴っ飛ばしたい



Unityによるゲーム制作#2

少しづつではあるが形になってきたので、一旦備忘録
参考
【Unity2D】Unityで2Dミニゲームを作るチュートリアル(第1回) - Qiita
【Unity2D】Spriteを左右反転する方法 - Qiita
Unityプログラミング基礎 (変数からclassまで) - Qiita
【Unity】 Rigidbodyの移動方法 - エフアンダーバー

一番お世話になったのは、一番上のブログ
.csファイル二つはそこで挙げられているものをそのまま流用
githubの学生プランでprivateリポジトリを作って、バージョン管理

現在の状況 (はてなブログって動画あげられないんだ...)


魚が餌であるエビに向かって泳ぐ
背景とエビは拾ったやつ
魚は友人に10分くらいで書いてもらった
制作時間約15時間


以下スクリプト
あくまで初心者が書いたものなので、間違っている部分があるはず
間違ってたら教えてください
Fish2.cs (Fish.csでないのは作り直したからで、深い意味はない)

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

/// Token (流用)を継承
public class Fish2 : Token {

	// Use this for initialization
	void Start () {
		// サイズを設定
		SetSize (SpriteWidth / 2, SpriteHeight / 2);
	}

	// Update is called once per frame
	void Update () {
		// カメラの左下座標を取得
		Vector2 min = GetWorldMin ();
		// カメラの右上座標を取得
		Vector2 max = GetWorldMax ();
		if (X < min.x || max.x < X) {
			// 画面外に出たので、X移動量を反転する
			VX *= -1;
			// 画面内に移動する
			ClampScreen ();
		}
		if (Y < min.y || max.y < Y) {
			VY *= -1;
			ClampScreen ();
		}
/// ここまでは1番目のブログを丸パクリ

/// 2番目のブログより
/// VX, VYはToken中で定義されている
		// 魚を進行方向へ向かせる
		// Vector3でscaleを取得し、VX(移動量)の向きで場合分け
		Vector3 scale = transform.localScale;
		if (VX > 0) {
			scale.x = -1;
		} else if (VX < 0) {
			scale.x = 1;
		} else {
		}
		// scaleを代入する
		transform.localScale = scale;

/// 魚っぽくするために、Update()で減速するようにした
		// 魚を減速させる
		VX *= 0.9f;
		VY *= 0.9f;

		// 止まった場合、魚を動かす
                // ここ上の方の条件分岐に入れれると思う
		if (VX == 0) {
			// ランダムな方向に移動する
			// 方向をランダムに決める
                        // SetVelocityもToken中で定義されている
			float dir = Random.Range (0, 359);
			float spd = Random.Range (0, 10);
			SetVelocity (dir, spd);
		}

/// ここが一番苦労した
/// Ebiオブジェクトをさがして、Vector2変数に打ち込む
/// Fish2は魚のスプライトにアタッチしているので、thisでok
/// Distance関数で距離を取得
		// エビと自分の距離
		Vector2 Ebipos = GameObject.Find("Ebi").transform.position;
		Vector2 Fish2pos = this.transform.position;
		float dis = Vector2.Distance (Ebipos, Fish2pos);
		Debug.Log ("Distance : " + dis);

/// 魚とエビの距離が8より小さい時、魚とエビの角度を取得して、その方向へ力を加える
		if (dis < 8f) {
			Vector2 dir = Ebipos - Fish2pos;
			RigidBody.AddForce (dir * 20f);
		}
	}
}

Fish2には、Rigidbody2DとColliderをGUIからアタッチ
重力はなしで、is Triggerをチェック
prefab化

Ebi.cs

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

public class Ebi : Token {


	// Use this for initialization
	void Start () {
		SetSize (SpriteWidth / 2, SpriteHeight / 2);
	}
	
	// Update is called once per frame
	void Update () {
		
		// 画面内にいるようにする
		Vector2 min = GetWorldMin ();
		Vector2 max = GetWorldMax ();
		if (X < min.x || max.x < X) {
			VX *= -0.1f;
			ClampScreen ();
		}
		if (Y < min.y || max.y < Y) {
			VY *= -0.1f;
			ClampScreen ();
		} 
	}
/// ここまではFish2と一緒

	// 魚と触れたとき
	void OnTriggerEnter2D(Collider2D c){
		// 消える
		DestroyObj();
	}
}

EbiにもRigidbody2DとColliderをアタッチ
水の中なので、重力は小さめに設定、is Triggerにチェック
prefab化

CreatEbi.cs (??"クリエイトebi!!")

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

public class CreateEbi : Token {
	
	// 生成したいPrefab
	public GameObject Ebi;

	// クリックした座標
	private Vector3 clickPosition;

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

	// Update is called once per frame
	void Update () {
		
		// 左クリックをした瞬間,0は左クリック
		if (Input.GetMouseButtonDown (0)) {

			clickPosition = Input.mousePosition;
			clickPosition.z = 10f;

			// 一度、"ebi"というなまえにして、"Ebi"に戻すことで(clone)が名前に付くのを防ぐ
			GameObject ebi = Instantiate(Ebi, Camera.main.ScreenToWorldPoint(clickPosition), new Quaternion()) as GameObject;
			ebi.name = "Ebi";
		}
	}
}

CreateEbiスクリプトヒエラルキーウィンドウにCreateEbiというフォルダ?を作ってそこにアタッチ
ヒエラルキーウィンドウにあるCreateEbiをクリックすると、インスペクターウィンドウ上にCreateEbiスクリプトが出てくる。そこに、Ebiのprefabをセットする。

挙動を見ると分かるが、エビが何個あろうと一つのエビ(一番古いエビ)との距離しかとってくれない
これでいいかもしれないが、全てのエビに対しての距離をとってほしかった(for文で繰り返すといいのか?)

あとはHPとか作って、死んだり増えたりする魚育成ゲームにしようと思う
このプロジェクトが終わったら一度横スクロールゲームを作ってみたい

プログラミング初心者がここまでできるUnityは神
オブジェクティブ指向とかは、いまでもよくわからん部分がある
構造を直してた時間が非常に多かった
なににせよ、新しい趣味ができてよかった