質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.34%

  • C#

    8230questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • Unity

    4886questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。

  • Unity2D

    1074questions

Unity シューティングゲームでの移動について

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 2,509

naop

score 2

前提・実現したいこと

Unityの学習でiPhone用シューティングゲームを制作しています。
自機の移動について質問させてください。

以下のサイト様のサンプルコードを参考に自機の相対移動を実装しました。
http://qiita.com/Nicky/items/d5fa514243cb65a5d4d4

このソースを元に自機のショットボタンをタッチする機能を付加したいです。
・移動しながらショットボタンを押すことで、移動しながらショットを発射できる
・ショットボタンを押している最中でも2本目の指で移動できる

発生している問題

1本指での操作だと想定通りの移動をしてくれます。
(移動の指を置きなおしても、自機の現在地から移動を再開する)
ですが、2本指となると挙動がおかしくなります。

・移動のドラッグ操作(A)→ショットボタンを押しっぱなし(B)→移動の指の置きなおし(C)
└(A)の指を離した座標と(C)の座標の差分だけ自機が瞬間移動する。
瞬間移動後は正常な動作。

・ショットボタンを押しっぱなし(A)→移動のためにタッチ(B)
└(B)の位置へ自機が瞬間移動する。
瞬間移動後は(B)の指に追従する

自機オブジェクトにアタッチしたソースコード

using UnityEngine;
using System.Collections;

public class PlayerMove : MonoBehaviour
{

    //移動関連
    public float adjustment = 0.3f;//カメラ位置で調整
    public GameObject shotButton;//ショットボタン
    public GameObject moveArea;//タッチ範囲

    private Vector3 playerPos;
    private Vector3 mousePos;

    void Update()
    {
        playerControl();
        clamp();
    }

    //プレイヤーの操作
    private void playerControl()
    {
        //タッチ入力があったら
        if (Input.touchCount > 0)
        {
            //全てのタッチを判定
            for (int i = 0; i < Input.touchCount; i++)
            {
                //移動エリアを取得
                Vector3 aTapPoint = Camera.main.ScreenToWorldPoint(Input.GetTouch(i).position);
                Collider2D aCollider2d = Physics2D.OverlapPoint(aTapPoint);
                GameObject obj = aCollider2d.transform.gameObject;

                //移動エリアのタッチなら
                if (obj == moveArea)
                {
                    if (Input.GetMouseButtonDown(0))
                    {
                        playerPos = this.transform.position;
                        mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
                    }

                    if (Input.GetMouseButton(0))
                    {
                        Vector3 diff = Camera.main.ScreenToWorldPoint(Input.mousePosition) - mousePos;

                        diff = Camera.main.ScreenToWorldPoint(Input.GetTouch(i).position) - mousePos;
                        diff.z = 0.0f;
                        this.transform.position = playerPos + diff;

                    }

                    if (Input.GetMouseButtonUp(0))
                    {
                        playerPos = Vector3.zero;
                        mousePos = Vector3.zero;
                    }
                }
            }
        }
    }

    //プレイヤーの移動制限
    void clamp()
    {
        // 画面左下のワールド座標をビューポートから取得
        Vector2 min = Camera.main.ViewportToWorldPoint(new Vector2(0, 0));

        // 画面右上のワールド座標をビューポートから取得
        Vector2 max = Camera.main.ViewportToWorldPoint(new Vector2(1, 1));

        // プレイヤーの座標を取得
        Vector2 pos = transform.position;

        // プレイヤーの位置が移動可能エリアに収まるように制限をかける
        pos.x = Mathf.Clamp(pos.x, -2.0f, max.x);
        pos.y = Mathf.Clamp(pos.y, min.y, 1.0f);

        // 制限をかけた値をプレイヤーの位置とする
        transform.position = pos;
    }

}

試したこと

自機の移動制限であるclampメソッドをコメントアウトしても挙動は変わりませんでした。
当初はタッチした指の本数やFingerIDで制御しようかとしましたが、
どこをタッチしたかで制御したほうが簡単かと思い、上記のコードとしました。
上記のコードの修正以外にも、他に良い方法等がございましたらご教示ください。

補足情報(言語/FW/ツール等のバージョンなど)

Unity5.4.1

追記

複数タッチ時、Input.GetMouseButtonUp(0)が反応していないことが原因のようです。
この問題を解決するためのアルゴリズムを模索中ですが、よい案がございましたらご教示ください。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

check解決した方法

0

自己解決いたしました。
原因はInput.mousePositionを使用したことによるものだったようです。
最終的なコードは以下のようになりました。

using UnityEngine;
using System.Collections;

public class PlayerMove : MonoBehaviour
{

    //移動関連
    //public float adjustment = 0.3f;//カメラ位置で調整
    public GameObject shotButton;//ショットボタン
    public GameObject moveArea;//タッチ範囲

    private Vector3 playerPos;
    private Vector3 mousePos;
    private int touchFinger = -1;

    private Vector3 test;

    void Start()
    {
        test = this.transform.position;
    }

    void Update()
    {
        playerControl();
        clamp();
    }

    //プレイヤーの操作
    private void playerControl()
    {
        //タッチ入力があったら
        if (Input.touchCount > 0)
        {
            //全てのタッチを判定
            for (int i = 0; i < Input.touchCount; i++)
            {
                //移動エリアを取得
                Vector3 aTapPoint = Camera.main.ScreenToWorldPoint(Input.GetTouch(i).position);
                Collider2D aCollider2d = Physics2D.OverlapPoint(aTapPoint);
                GameObject obj = aCollider2d.transform.gameObject;

                //移動エリアのタッチなら
                if (obj == moveArea)
                {
                    if (Input.GetTouch(i).phase == TouchPhase.Began)
                    {
                        touchFinger = Input.GetTouch(i).fingerId;
                        playerPos = this.transform.position;
                        mousePos = Camera.main.ScreenToWorldPoint(Input.GetTouch(i).position);//スクリーン座標をワールド座標へ
                    }
                    if ((Input.GetTouch(i).phase == TouchPhase.Moved) && Input.GetTouch(i).fingerId == touchFinger)
                    {
                        Vector3 prePos = this.transform.position;
                        Vector3 diff = Camera.main.ScreenToWorldPoint(Input.GetTouch(touchFinger).position) - mousePos;
                        diff.z = 0.0f;
                        this.transform.position = playerPos + diff;
                    }

                    if (Input.GetTouch(touchFinger).phase == TouchPhase.Ended)
                    {
                        playerPos = Vector3.zero;
                        mousePos = Vector3.zero;
                    }
                }

            }
        }
    }

    //プレイヤーの移動制限
    void clamp()
    {
        // 画面左下のワールド座標をビューポートから取得
        Vector2 min = Camera.main.ViewportToWorldPoint(new Vector2(0, 0));

        // 画面右上のワールド座標をビューポートから取得
        Vector2 max = Camera.main.ViewportToWorldPoint(new Vector2(1, 1));

        // プレイヤーの座標を取得
        Vector2 pos = transform.position;

        // プレイヤーの位置が移動可能エリアに収まるように制限をかける
        pos.x = Mathf.Clamp(pos.x, -2.0f, max.x);
        pos.y = Mathf.Clamp(pos.y, min.y, 1.0f);

        // 制限をかけた値をプレイヤーの位置とする
        transform.position = pos;
    }

}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.34%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • C#

    8230questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • Unity

    4886questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。

  • Unity2D

    1074questions