読者です 読者をやめる 読者になる 読者になる

AIプログラムとかUnityゲーム開発について

探索や学習などを活用したAI系ゲームを作りたいと思います。

マウスでクリックした位置にキャラを動かす(2D)

Unity2D

f:id:yasu9780:20160118013925p:plain

しばらくUnityでプログラム作ってなかったので基本的な操作がわからなくなったので、リハビリをかねて基礎からやってみました。
2Dで、マウスをクリックした位置にキャラを動かすというもので、スマホゲームだとUI的にクリック位置に移動のほうが良いし。
今まではキーボードで押した方向に動かすみたいなことしかしてなかったので、色々はまりました。

画像は、素材サイトからお借りして、spriteEditorでsliceしてます。
ねくらマップチップのいろいろ


以前やった時はanimatorをつかってましたが、今回は、8方向の移動でアニメーションを切り替える必要があり、いちいちanimatorでやってたら面倒すぎるので、

GetComponent<SpriteRenderer>().sprite = charas[animStart+animIndex];

読み込んだspriteの該当位置を、キャラの移動方向で切り替えてアニメーションするようにしました。
ちなみにspriteは、

charas = Resources.LoadAll<Sprite>("20151213130550bd9");

これでslice後の複数spriteをsprite配列に読み込めます。
spriteはRigidbody2D(GravityScaleは0)とBoxCollider2Dをつけてます。
障害物は、BoxCollider2Dのみ。

わかりにくかったのが、移動方向に応じて8種類のアニメーションを切り替える場面で、3Dなら何も意識しないでいいけど2dはかえって面倒くさい。

以下のように、現在位置から目標位置への正規化ベクトルを求めて、そのベクトルで8方向アニメを切り替えました。
なにかもっとスマートな方法がありそうですけどね。角度にしてしまえば、もっと楽だと思う。

angle = (rb2D.position-target).normalized;
if(angle.x<-0.2 && angle.y>0.2) animStart = 9;
if(angle.x>0.2 && angle.y>0.2) animStart = 3;
if(angle.x<-0.2 && angle.y<-0.2) animStart = 21;
if(angle.x>0.2 && angle.y<-0.2) animStart = 15;
if(Mathf.Abs(angle.y)<=0.2 && angle.x<0) animStart = 12;
if(Mathf.Abs(angle.y)<=0.2 && angle.x>0) animStart = 6;
if(Mathf.Abs(angle.x)<=0.2 && angle.y<0) animStart = 18;
if(Mathf.Abs(angle.x)<=0.2 && angle.y>0) animStart = 0;

目的地に付くか、なにかに衝突したら速度0にしてアニメーション止めます。


以下ソース

using UnityEngine;
using System.Collections;

public class Player : MonoBehaviour {

	private float speed = 5.0f; //プレイヤーの速さ
	private int animIndex; //歩くアニメーションのインデックス
	private int animStart=0;
	private bool walkCheck; //歩いているかのチェック
	private Vector2 target;
	private Rigidbody2D rb2D;
	private Sprite[] charas;
	private Vector2 angle;

	void Start () {
		rb2D = GetComponent <Rigidbody2D> ();
		animStart=0;
		animIndex = 0;
		walkCheck = false;
		charas = Resources.LoadAll<Sprite>("20151213130550bd9");
	}

	void Update () {
		if (Input.GetMouseButton(0))
		{
			target = Camera.main.ScreenToWorldPoint(Input.mousePosition);
			walkCheck = true;
		}

		//歩いていたら歩くアニメーションの再生
		if (walkCheck)
		{
			animIndex++;
			if ( animIndex >= 3) animIndex = 0;
			GetComponent<SpriteRenderer>().sprite = charas[animStart+animIndex];

			float sqrRemainingDistance = (rb2D.position-target).sqrMagnitude;
			if(sqrRemainingDistance > float.Epsilon)
			{
				Vector2 newPostion =  Vector2.MoveTowards(rb2D.position, target, speed * Time.deltaTime);
				rb2D.MovePosition (newPostion);
/*
0 ↓
3 ↓←
6 ←
9 ↓→
12 → 
15 ↑← 
18 ↑ 
21 ↑→ 
*/
				angle = (rb2D.position-target).normalized;
//				Debug.Log("angle="+angle.x+","+angle.y);
				if(angle.x<-0.2 && angle.y>0.2) animStart = 9;
				if(angle.x>0.2 && angle.y>0.2) animStart = 3;
				if(angle.x<-0.2 && angle.y<-0.2) animStart = 21;
				if(angle.x>0.2 && angle.y<-0.2) animStart = 15;
				if(Mathf.Abs(angle.y)<=0.2 && angle.x<0) animStart = 12;
				if(Mathf.Abs(angle.y)<=0.2 && angle.x>0) animStart = 6;
				if(Mathf.Abs(angle.x)<=0.2 && angle.y<0) animStart = 18;
				if(Mathf.Abs(angle.x)<=0.2 && angle.y>0) animStart = 0;
			}
			else
			{
				GetComponent<Rigidbody2D>().velocity = Vector2.zero;
				walkCheck=false;
			}
		}
   	}

	void OnCollisionEnter2D(Collision2D coll) {
		GetComponent<Rigidbody2D>().velocity = Vector2.zero;
		walkCheck=false;
	}

	// テキスト表示
	void OnGUI()
	{
		// 説明テキスト
		GUI.TextField(new Rect(5, 5, 400, 40), "ゲーム画面上でマウスの左クリックした位置に移動する");
		// リセットボタン
		if (GUI.Button(new Rect(5, 50, 110, 30), "リセットボタン"))
		{
		    Application.LoadLevel(Application.loadedLevelName);
		}
	}
}