UnityでフォートナイトみたいなTPSを作るチュートリアル

今回つくるもの

こんな感じのTPSを作ります

今回やること

  • ステージの作成
  • プレイヤーの設定
  • プレイヤーの移動
  • アニメーターの設定
  • 敵を倒せるようにする
  • 敵の作成
ステージの作成

こちらにまとめておきましたので参考にして下さい

プレイヤーの設定

こちらで作成したモデルを入れていきます

Unityの細かな操作方法、設定等は漫画にまとめておきましたので、操作が分からなかった場合は参考にして下さい

素材を作るの面倒くさいよーって人はこちらにまとめておいたのでダウンロードしてからインポートして下さい
プレイヤー以外にも銃、照準も入れてありますのでそれらを使いたい場合もダウンロードして下さい

インポートしたら、待機アニメーションと銃をドラッグ&ドロップします

プレイヤーを選択し、AddComponentをおして、CharacterControllerとCapsuleColliderを取り付け、数値を設定してちょうどいいように合わせます

MainCameraをプレイヤーに、銃をプレイヤーのLeftHandにドラッグ&ドロップします

銃をちょうどいい位置、向き、大きさに合わせます

カメラもちょうど良い位置に合わせます

プレイヤーの移動

プレイヤーが移動するようにプログラミングしていきます
今回はマウスの移動で視点切り替え、WASDで前後左右の移動をできるようにします

Playerというスクリプトを作成して以下を入力していきます

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

public class Player : MonoBehaviour {

	private CharacterController characterController;//①CharacterController型の変数
	private Vector3 Velocity;//①キャラクターコントローラーを動かすためのVector3型の変数
	public float JumpPower;//①ジャンプ力
	public Transform verRot;//①縦の視点移動の変数(カメラに合わせる)
	public Transform horRot;//①横の視点移動の変数(プレイヤーに合わせる)
	public float MoveSpeed;//①移動速度

	// Use this for initialization
	void Start () {
		characterController = GetComponent <charactercontroller> ();//①CharacterControllerを変数に代入
	}

	// Update is called once per frame
	void Update ()
	{
		float X_Rotation = Input.GetAxis ("Mouse X");//①X_RotationにマウスのX軸の動きを代入する
		float Y_Rotation = Input.GetAxis ("Mouse Y");//①Y_RotationにマウスのY軸の動きを代入する
		horRot.transform.Rotate (new Vector3 (0, X_Rotation * 2, 0));//①プレイヤーのY軸の回転をX_Rotationに合わせる
		verRot.transform.Rotate (-Y_Rotation * 2, 0, 0);//①カメラのX軸の回転をY_Rotationに合わせる

		if (Input.GetKey (KeyCode.W))//①Wキーがおされたら 
		{
			characterController.Move (this.gameObject.transform.forward * MoveSpeed * Time.deltaTime);//①前方にMoveSpeed*Time.deltaTimeだけ動かす
		} 

		if (Input.GetKey (KeyCode.S))//①Sキーがおされたら
		{
			characterController.Move (this.gameObject.transform.forward * -1f * MoveSpeed * Time.deltaTime);//①後方にMoveSpeed*Time.deltaTimeだけ動かす
		} 
			
		if (Input.GetKey (KeyCode.A))//①Aキーがおされたら 
		{
			characterController.Move (this.gameObject.transform.right * -1 * MoveSpeed * Time.deltaTime);//①左にMoveSpeed*Time.deltaTimeだけ動かす
		} 
			
		if (Input.GetKey (KeyCode.D))//①Dキーがおされたら 
		{
			characterController.Move (this.gameObject.transform.right * MoveSpeed * Time.deltaTime);//①右にMoveSpeed*Time.deltaTimeだけ動かす
		}  

		characterController.Move (Velocity);//①キャラクターコントローラーをVelocityだけ動かし続ける
		Velocity.y += Physics.gravity.y * Time.deltaTime;//①Velocityのy軸を重力*Time.deltaTime分だけ動かす

		if (characterController.isGrounded)//①キャラクターコントローラーが地面に接触している時に
		{
			if (Input.GetKeyDown (KeyCode.Space))//①スペースキーがおされたら
			{
				Velocity.y = JumpPower;//①Velocity.yをJumpPowerにする
			}
		}
	}
}

作成し終えたらVarRotにはMainCamera、HorRotにはプレイヤーをドラッグ&ドロップし、JumpPower、MoveSpeedには数値の入力を行います

アニメーションをつける

こちらを参考にアニメーターの設定をしましょう
※こちらの説明だと攻撃のアニメーションも追加していますが今回は攻撃は設定しないので走るだけ設定してください
 変数もRunのみ作成で大丈夫です

続いてPlayerスクリプトに追記します
コメントを記載しているところが追記部分です

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

public class Player : MonoBehaviour {

	private CharacterController characterController;
	private Vector3 Velocity;
	public float JumpPower;
	public Transform verRot;
	public Transform horRot;
	public float MoveSpeed;
        private Animator anim;//②Animator型の変数

	// Use this for initialization
	void Start () {
		characterController = GetComponent <charactercontroller> ();
		anim = GetComponent<animator> ();//②Animatorを変数に代入
	}

	// Update is called once per frame
	void Update ()
	{
		float X_Rotation = Input.GetAxis ("Mouse X");
		float Y_Rotation = Input.GetAxis ("Mouse Y");
		horRot.transform.Rotate (new Vector3 (0, X_Rotation * 2, 0));
		verRot.transform.Rotate (-Y_Rotation * 2, 0, 0);

		if (Input.GetKey (KeyCode.W))//
		{
			characterController.Move (this.gameObject.transform.forward * MoveSpeed * Time.deltaTime);
			anim.SetBool ("Run", true);//②アニメーターのRunをtrueにする
		} 

		else if (Input.GetKeyUp (KeyCode.W))//②Wキーがはなされたら 
		{
			anim.SetBool ("Run", false);//②アニメーターのRunをfalseにする
		}

		if (Input.GetKey (KeyCode.S))
		{
			characterController.Move (this.gameObject.transform.forward * -1f * MoveSpeed * Time.deltaTime);
			anim.SetBool ("Run", true);//②アニメーターのRunをtrueにする
		} 

		else if (Input.GetKeyUp (KeyCode.S))//②Sキーがはなされたら 
		{
			anim.SetBool ("Run", false);//②アニメーターのRunをfalseにする
		}

		if (Input.GetKey (KeyCode.A)) 
		{
			characterController.Move (this.gameObject.transform.right * -1 * MoveSpeed * Time.deltaTime);
			anim.SetBool ("Run", true);//②アニメーターのRunをtrueにする
		} 

		else if (Input.GetKeyUp (KeyCode.A))//②Aキーがはなされたら 
		{
			anim.SetBool ("Run", false);//②アニメーターのRunをfalseにする
		}

		if (Input.GetKey (KeyCode.D))
		{
			characterController.Move (this.gameObject.transform.right * MoveSpeed * Time.deltaTime);
			anim.SetBool ("Run", true);//②アニメーターのRunをtrueにする
		} 

		else if (Input.GetKeyUp (KeyCode.D))//②Dキーがはなされたら 
		{
			anim.SetBool ("Run", false);//②アニメーターのRunをfalseにする
		} 

		characterController.Move (Velocity);
		Velocity.y += Physics.gravity.y * Time.deltaTime;

		if (characterController.isGrounded)
		{
			if (Input.GetKeyDown (KeyCode.Space))
			{
				Velocity.y = JumpPower;
			}
		}
	}
}
敵を倒せるようにする

敵を倒すにはRayという機能を使います
RayとはUnityについてる機能のことで、透明な光線を飛ばして、色々な判定を取ることができます

照準になる画像をいれます
Create → UI → Imageをおします

PosX、PosY、PosZを0にして、○をおして照準にしたい画像を選びます
照準の画像は自分で作ってもいいですし、初めの素材のダウンロードのところにも入っています

では、再びPlayerスクリプトに追記していきます

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

public class Player : MonoBehaviour {

	private CharacterController characterController;
	private Vector3 Velocity;
	public float JumpPower;
	public Transform verRot;
	public Transform horRot;
	public float MoveSpeed;
	private Animator anim;
	private Ray ray;//③Ray型の変数
	public GameObject Explosion;//③敵を倒した時に出現させる爆発
	private int distance = 10000;//③Rayを飛ばす距離
	private RaycastHit hit;//③Rayが何かに当たった時の情報
	public GameObject Muzzle;//③Rayを発射する場所

	// Use this for initialization
	void Start () {
		characterController = GetComponent <charactercontroller> ();
		anim = GetComponent<animator> ();
	}

	// Update is called once per frame
	void Update ()
	{
		float X_Rotation = Input.GetAxis ("Mouse X");
		float Y_Rotation = Input.GetAxis ("Mouse Y");
		horRot.transform.Rotate (new Vector3 (0, X_Rotation * 2, 0));
		verRot.transform.Rotate (-Y_Rotation * 2, 0, 0);

		if (Input.GetKey (KeyCode.W))
		{
			characterController.Move (this.gameObject.transform.forward * MoveSpeed * Time.deltaTime);
			anim.SetBool ("Run", true);
		} 

		else if (Input.GetKeyUp (KeyCode.W)) 
		{
			anim.SetBool ("Run", false);
		}

		if (Input.GetKey (KeyCode.S))
		{
			characterController.Move (this.gameObject.transform.forward * -1f * MoveSpeed * Time.deltaTime);
			anim.SetBool ("Run", true);
		} 

		else if (Input.GetKeyUp (KeyCode.S)) 
		{
			anim.SetBool ("Run", false);
		}

		if (Input.GetKey (KeyCode.A)) 
		{
			anim.SetBool ("Run", true);
			characterController.Move (this.gameObject.transform.right * -1 * MoveSpeed * Time.deltaTime);
		} 

		else if (Input.GetKeyUp (KeyCode.A))
		{
			anim.SetBool ("Run", false);
		}

		if (Input.GetKey (KeyCode.D)) 
		{
			anim.SetBool ("Run", true);
			characterController.Move (this.gameObject.transform.right * MoveSpeed * Time.deltaTime);
		} 

		else if (Input.GetKeyUp (KeyCode.D))
		{
			anim.SetBool ("Run", false);
		} 

		characterController.Move (Velocity);
		Velocity.y += Physics.gravity.y * Time.deltaTime;

		if (characterController.isGrounded)
		{
			if (Input.GetKeyDown (KeyCode.Space))
			{
				Velocity.y = JumpPower;
			}
		}

		if (Input.GetMouseButton(0))//③マウスが左クリックされたら 
		{
			Ray ray = new Ray(Muzzle.transform.position, Muzzle.transform.forward);//③RayをMuzzleの場所から前方に飛ばす
			Debug.DrawRay(ray.origin, ray.direction, Color.red);//③Rayを赤色で表示させる

			if (Physics.Raycast (ray, out hit, distance)) {//③Rayがdistanceの範囲内で何かに当たった時に

				if (hit.collider.tag == "Enemy")//③もし当たった物のタグがEnemyだったら 
				{
					Destroy (hit.collider.gameObject);//③当たった物を消去して、
					Instantiate (Explosion.gameObject, hit.collider.gameObject.transform.position, gameObject.transform.rotation);//③Rayが当たった場所に爆発を生成する
				}
			}
		}
	}
}

入力し終わったら爆発エフェクト、MainCameraをドラッグ&ドロップします
※爆発エフェクトはAssetStoreでダウンロードしておいて下さい

敵を作成する

今回はとりあえずCapsuleにしておきます(凝りたい人はプレイヤーの作成で行ったようなことをやってみて下さい)
Create → 3DObject → Capsuleをおします

動きはシンプルにプレイヤーに向かってくるようにします
新しくEnemyスクリプトを作成し、以下を入力していきます

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

public class NewBehaviourScript : MonoBehaviour
{
	public GameObject target;//敵がついていくターゲット

    // Update is called once per frame
    void Update()
    {
		transform.LookAt (target.transform);//ターゲットの方を向く
		transform.position += transform.forward * 10f * Time.deltaTime;//向いている方向に進む
    }
}

入力してスクリプトをCapsuleにつけてTargetの部分にプレイヤーをドラッグ&ドロップします

敵にEnemyというタグをつけます
敵を選択し、Untagged → AddTagをおします

Enemyと入力し、Saveをおします

作成した敵は複製して色々な場所に配置しましょう
また、こちらのスクリプトを敵に入力すれば、徘徊したり、近づいたら向かってくるなど、簡易的なAIが作れます

ゲームクリアをつくる

Create → UI → Textをおします

画像のように調整します

敵を全員倒すとClearの文字が表示されるようにPlayerスクリプトに追記していきます

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

public class Player : MonoBehaviour {

	private CharacterController characterController;
	private Vector3 Velocity;
	public float JumpPower;
	public Transform verRot;
	public Transform horRot;
	public float MoveSpeed;
	private Animator anim;
	private Ray ray;
	public GameObject Explosion;
	private int distance = 10000;
	private RaycastHit hit;
	public GameObject Muzzle;
	private GameObject[] enemyObjects;//④敵の数を取得するための配列
	public GameObject Clear;//④クリア時に出現する文字

	// Use this for initialization
	void Start () {
		characterController = GetComponent <charactercontroller> ();
		anim = GetComponent<animator> ();
		Clear.SetActive (false);//④Clearの文字を非表示にする
	}

	// Update is called once per frame
	void Update ()
	{
		float X_Rotation = Input.GetAxis ("Mouse X");
		float Y_Rotation = Input.GetAxis ("Mouse Y");
		horRot.transform.Rotate (new Vector3 (0, X_Rotation * 2, 0));
		verRot.transform.Rotate (-Y_Rotation * 2, 0, 0);

		if (Input.GetKey (KeyCode.W))
		{
			characterController.Move (this.gameObject.transform.forward * MoveSpeed * Time.deltaTime);
			anim.SetBool ("Run", true);
		} 

		else if (Input.GetKeyUp (KeyCode.W)) 
		{
			anim.SetBool ("Run", false);
		}

		if (Input.GetKey (KeyCode.S))
		{
			characterController.Move (this.gameObject.transform.forward * -1f * MoveSpeed * Time.deltaTime);
			anim.SetBool ("Run", true);
		} 

		else if (Input.GetKeyUp (KeyCode.S)) 
		{
			anim.SetBool ("Run", false);
		}

		if (Input.GetKey (KeyCode.A)) 
		{
			characterController.Move (this.gameObject.transform.right * -1 * MoveSpeed * Time.deltaTime);
			anim.SetBool ("Run", true);
		} 

		else if (Input.GetKeyUp (KeyCode.A))
		{
			anim.SetBool ("Run", false);
		}

		if (Input.GetKey (KeyCode.D))
		{
			anim.SetBool ("Run", true);
			characterController.Move (this.gameObject.transform.right * MoveSpeed * Time.deltaTime);
		} 

		else if (Input.GetKeyUp (KeyCode.D))
		{
			anim.SetBool ("Run", false);
		} 

		characterController.Move (Velocity);
		Velocity.y += Physics.gravity.y * Time.deltaTime;

		if (characterController.isGrounded)
		{

			if (Input.GetKeyDown (KeyCode.Space))
			{
				Velocity.y = JumpPower;
			}
		}

		if (Input.GetMouseButton(0)) 
		{
			Ray ray = new Ray(Muzzle.transform.position, Muzzle.transform.forward);
			Debug.DrawRay(ray.origin, ray.direction, Color.red);

			if (Physics.Raycast (ray, out hit, distance)) 
			{
				if (hit.collider.tag == "Enemy") 
				{
					Destroy (hit.collider.gameObject);
					Instantiate (Explosion.gameObject, hit.collider.gameObject.transform.position, gameObject.transform.rotation);
				}
			}
		}

		enemyObjects = GameObject.FindGameObjectsWithTag("Enemy");//④enemyObjectsにEnemyのタグがついているオブジェクトを代入する

		if (enemyObjects.Length == 0)//④もしenemyObjectsの数が0なら
		{
			Clear.SetActive (true);//④Clearを表示する
		}
	}
}

入力し終わったらClearの文字をドラッグ&ドロップします

テストプレイすると、WASDで走って、マウスで向きが変わり、スペースでジャンプします
クリックすると敵を倒すことができますね

以上で一応出来上がりです♪

番外編:マウスのカーソルの管理

PCでプレイをするとマウスのカーソルが表示されていたり、画面外に出たりと、邪魔くさかったりします
それを直すには以下のように追記します

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

public class Player : MonoBehaviour {

	private CharacterController characterController;
	private Vector3 Velocity;
	public float JumpPower;
	public Transform verRot;
	public Transform horRot;
	public float MoveSpeed;
	private Animator anim;
	private Ray ray;
	public GameObject Explosion;
	private int distance = 10000;
	private RaycastHit hit;
	public GameObject Muzzle;
	private GameObject[] enemyObjects;
	public GameObject Clear;
        private CursorLockMode wantedMode = CursorLockMode.None;//⑤マウスのカーソルの状態を初期化

	// Use this for initialization
	void Start () {
		characterController = GetComponent <charactercontroller> ();
		anim = GetComponent<animator> ();
		Clear.SetActive (false);
	}

	// Update is called once per frame
	void Update ()
	{
		float X_Rotation = Input.GetAxis ("Mouse X");
		float Y_Rotation = Input.GetAxis ("Mouse Y");
		horRot.transform.Rotate (new Vector3 (0, X_Rotation * 2, 0));
		verRot.transform.Rotate (-Y_Rotation * 2, 0, 0);
                Cursor.lockState = wantedMode;//⑤マウスカーソルの状態を操作できるようにする
                Cursor.lockState = wantedMode = CursorLockMode.Confined;//⑤マウスカーソルの状態を画面内にロックする
                Cursor.visible = false;//⑤マウスのカーソルを非表示にする
		
                if (Input.GetKey (KeyCode.W))
		{
			characterController.Move (this.gameObject.transform.forward * MoveSpeed * Time.deltaTime);
			anim.SetBool ("Run", true);
		} 

		else if (Input.GetKeyUp (KeyCode.W)) 
		{
			anim.SetBool ("Run", false);
		}

		if (Input.GetKey (KeyCode.S))
		{
			characterController.Move (this.gameObject.transform.forward * -1f * MoveSpeed * Time.deltaTime);
			anim.SetBool ("Run", true);
		} 

		else if (Input.GetKeyUp (KeyCode.S)) 
		{
			anim.SetBool ("Run", false);
		}

		if (Input.GetKey (KeyCode.A)) 
		{
			characterController.Move (this.gameObject.transform.right * -1 * MoveSpeed * Time.deltaTime);
			anim.SetBool ("Run", true);
		} 

		else if (Input.GetKeyUp (KeyCode.A))
		{
			anim.SetBool ("Run", false);
		}

		if (Input.GetKey (KeyCode.D))
		{
			anim.SetBool ("Run", true);
			characterController.Move (this.gameObject.transform.right * MoveSpeed * Time.deltaTime);
		} 

		else if (Input.GetKeyUp (KeyCode.D))
		{
			anim.SetBool ("Run", false);
		} 

		characterController.Move (Velocity);
		Velocity.y += Physics.gravity.y * Time.deltaTime;

		if (characterController.isGrounded)
		{

			if (Input.GetKeyDown (KeyCode.Space))
			{
				Velocity.y = JumpPower;
			}
		}

		if (Input.GetMouseButton(0)) 
		{
			Ray ray = new Ray(Muzzle.transform.position, Muzzle.transform.forward);
			Debug.DrawRay(ray.origin, ray.direction, Color.red);

			if (Physics.Raycast (ray, out hit, distance)) 
			{
				if (hit.collider.tag == "Enemy") 
				{
					Destroy (hit.collider.gameObject);
					Instantiate (Explosion.gameObject, hit.collider.gameObject.transform.position, gameObject.transform.rotation);
				}
			}
		}

		enemyObjects = GameObject.FindGameObjectsWithTag("Enemy");//④enemyObjectsにEnemyのタグがついているオブジェクトを代入する

		if (enemyObjects.Length == 0)//④もしenemyObjectsの数が0なら
		{
			Clear.SetActive (true);//④Clearを表示する
		}
	}
}

ただ、こちらビルドしないと反映されません
アプリ化とかもしたい場合はこちらを追記すると良いでしょう
お疲れ様でした♪

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメント一覧 (3件)

  • 初めまして、ゲタバコ先生
    私は、面白いゲームを自作できるようになりたいと、先生のサイトにたどり着きました。
    今回ですが、学習中に続行不可能な箇所がありましたため、ご連絡差し上げました。

    対象箇所ですが、Unitydeフォートナイトみたいなtpsを作るチュートリアル
    上記のキャラクターと銃をダウンロードするファイルには、キャラクターしか入っておりませんでした。

    • 返事だいぶ遅れてしまい、すみません
      データ移行等の関係で消えてしまったようです
      お手数ですがAssetStore等で好きな銃をお探しくださいませ

コメントする

CAPTCHA


このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

目次