Unity ゲーム開発日記:プレイヤーを動かす
はじめに
2Dシューティングゲーム「オシャレなロケット:Oshare-Na-Rocket」のシステムを作っていきます。
今回はプレイヤーを動かすシステムを作ります。
参考
主に公式のチュートリアルを参考にします。
チュートリアルでは2Dモードで作成していますが、 私は3Dモードで作成します(ゲーム自体は基本的に2Dです)。
以下の記事はPlayerを進行方向へ向けるときに参考にさせていただきました
背景を黒に
Main Camera の "Clear Flag" を "Solid Color" にして色を黒にします
背景はとりあえずこれで良しとします
プレイヤーのオブジェクトを作成
Create > 2D Objects > Sprite を選択
名前は "Player" にします
Player の Sprite に "Knob" を選択すると、黒い背景に白い点が現れます
そしてPlayerに "Rigidbody" をアタッチ
Rigidbodyをアタッチすると、そのオブジェクトを物理的に制御できます
タッチ(マウス)でプレイヤーを操作
タッチ、またはマウスでプレイヤーを動かします
本来はスマートフォンのタッチ操作で動かすことになりますが、 Unityエディタ上ではマウスで動かします
方法
- タッチを始めた座標(スクリーン座標)を取得
- 指をスライドさせた後の座標を取得
- 1と2からプレイヤーが移動する方向を計算
- プレイヤー移動
タッチ操作のための関数を作成
// タッチを始めた座標
Vector2 TouchPositionFrist;
void PlayerTouch () { // タッチ数をカウント、0より大きい場合(つまりタッチがある場合) if (Input.touchCount > 0) { Touch touch = Input.GetTouch(0); // タッチを始めた時 if (touch.phase == TouchPhase.Began) { //タッチを始めた座標を取得 TouchPositionFrist = touch.position; } // 指をスライドさせている時 else if (touch.phase == TouchPhase.Moved) { // プレイヤーを移動させる関数へ座標を渡す PlayerMove(TouchPositionFrist, touch.position); } // 指を離した時 if (touch.phase == TouchPhase.Ended) { // プレイヤーの速度を0にする PlayerRigidbody.velocity = new Vector3(0, 0, 0); } } }
プレイヤーを動かす関数
void Start () { // プレイヤーのRigidbodyコンポーネントを取得 PlayerRigidbody = GetComponent<Rigidbody>(); }
void PlayerMove (Vector3 v1, Vector3 v2) { // 二つのベクトルから指をスライドさせた方向を求める Vector3 direction = (v2 - v1).normalized; // 指をスライドさせた方向とは逆向きにプレイヤーを移動 PlayerRigidbody.velocity = -direction * PlayerSpeed; }
プレイヤーに進行方向を向かせる
PlayerMove関数に追加
void PlayerMove (Vector3 v1, Vector3 v2) { Vector3 direction = (v2 - v1).normalized; PlayerRigidbody.velocity = direction * PlayerSpeed; // 進行方向に向かせる(2Dであることに気をつける) float angle = GetAngle(direction); transform.eulerAngles = new Vector3(0, 0, angle); }
アークタンジェントを使ってZ軸の向きを求める
float GetAngle(Vector3 v) { float rad = Mathf.Atan2(v.y, v.x); return rad * Mathf.Rad2Deg; }
移動制限を設ける
Start関数でスクリーンの大きさを取得します
プレイヤーをスクリーン内で動かすようにするためです
Camera.main.ScreenToWorlePoint
でカメラがNullだよみたいなエラーが出た場合、
CameraのTagが設定されていない可能性があります。CameraのTagを"MainCamera"にすると直ります。
void Start () { Debug.Log("!!START!!"); playerRigidbody = GetComponent<Rigidbody>(); // スクリーンの大きさを取得 min = Camera.main.ScreenToWorldPoint(new Vector3(0, 0, 10f)); max = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, 10f)); }
そしてPlayerMove関数を以下のように変更します。
Mathf.Clamp関数は定めた範囲から出た場合、内側に戻してくれます。
marginは余裕を持たせるために設定しました。
void PlayerMove (Vector3 v1, Vector3 v2) { // 指をスライドさせた方向に移動 Vector3 direction = (v2 - v1).normalized; playerRigidbody.velocity = direction * playerSpeed; // 進行方向に向かせる(2Dであることに気をつける) float angle = GetAngle(direction); transform.eulerAngles = new Vector3(0, 0, angle - 90f); // 移動制限を設ける Vector3 playerPosition = transform.position; float margin_x = max.x / 20f; float margin_y = max.y / 20f; playerPosition.x = Mathf.Clamp(playerPosition.x, min.x + margin_x, max.x - margin_x); playerPosition.y = Mathf.Clamp(playerPosition.y, min.y + margin_y, max.y - margin_y); transform.position = playerPosition; }
Camera.main.ScreenToWorlePointのエラーについて
今回書いたコード
おわりに
今回はプレイヤーを動かすシステムを作成しました
次は弾を発射するシステムを作っていきます