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

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

ただいまの
回答率

90.74%

  • C#

    6549questions

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

  • Unity

    3570questions

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

  • Unity2D

    756questions

unityで思っているように動作しない

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 268

Hayato555

score 10

前提・実現したいこと

unityでテトリスを作ってます。 今、テトリスのミノ(ブロック)の移動のスクリプトを書いているのですが、ある部分がうまく動作しません。 このコードは、キーボードの入力でミノを動かせるようにしているのですが、縦移動(下方向)に動かしているときは ミノの回転が可能なのですが、横移動をしているとき(右および左)の移動をしているときはミノの回転ができません。 また、1秒で1マス下に落ちるようになるはずなのに、ミノを動かしている間は約1.5秒ほどになってしまいます。
何度も見直してみたのですが、原因がわかりません。誰かわかりませんか?

該当のソースコード

using UnityEngine;
using System.Collections;

public class Imino : MonoBehaviour
{
    // Time since last gravity tick

    float lastFall = 0;

    public float verticalTimer = 0;
    public float horizontalTimer = 0;

    public float continuosVerticalSpeed = 0.05f;
    public float continuosHorizontalSpeed = 0.1f;

    public float buttonDownWaitMax = 0.2f;
    public float buttonDownWaitTimer = 0;


    public bool movedImediateHorizontal = false;
    public bool movedImediateVertical = false;






    public bool isValidGridPos()
    {
        foreach (Transform child in transform)
        {
            Vector2 v = Grid.roundVec2(child.position);

            // Not inside Border?
            if (!Grid.insideBorder(v))
                return false;

            // Block in grid cell (and not part of same group)?
            if (Grid.grid[(int)v.x, (int)v.y] != null &&
                Grid.grid[(int)v.x, (int)v.y].parent != transform)
                return false;
        }
        return true;
    }
    public void updateGrid()
    {
        // Remove old children from grid
        for (int y = 0; y < Grid.h; ++y)
            for (int x = 0; x < Grid.w; ++x)
                if (Grid.grid[x, y] != null)
                    if (Grid.grid[x, y].parent == transform)
                        Grid.grid[x, y] = null;

        // Add new children to grid
        foreach (Transform child in transform)
        {
            Vector2 v = Grid.roundVec2(child.position);
            Grid.grid[(int)v.x, (int)v.y] = child;
        }
    }
    void Update()
    {

        if (Input.GetKeyUp(KeyCode.D) || Input.GetKeyUp(KeyCode.A) || Input.GetKeyUp(KeyCode.S))
        {
            movedImediateHorizontal = false;
            movedImediateVertical = false;
            horizontalTimer = 0;
            verticalTimer = 0;
            buttonDownWaitTimer = 0;
        }

        // Move Left

        if (Input.GetKey(KeyCode.A))
        {
            if (movedImediateHorizontal)
            {
                if (buttonDownWaitTimer < buttonDownWaitMax)
                {
                    buttonDownWaitTimer += Time.deltaTime;
                    return;
                }




                if (horizontalTimer < continuosHorizontalSpeed)
                {
                    horizontalTimer += Time.deltaTime;
                    return;
                }
            }
            if (!movedImediateHorizontal)
            {
                movedImediateHorizontal = true;
            }

            horizontalTimer = 0;

            // Modify position
            transform.position += new Vector3(-1, 0, 0);

            // See if valid
            if (isValidGridPos())
            {

                // It's valid. Update grid.
                updateGrid();
            }
            else
                // It's not valid. revert.
                transform.position += new Vector3(1, 0, 0);
        }

        // Move Right
        if (Input.GetKey(KeyCode.D))
        {
            if (movedImediateHorizontal)
            {

                if (buttonDownWaitTimer < buttonDownWaitMax)
                {
                    buttonDownWaitTimer += Time.deltaTime;
                    return;
                }

                if (horizontalTimer < continuosHorizontalSpeed)
                {
                    horizontalTimer += Time.deltaTime;
                    return;
                }
            }
            if (!movedImediateHorizontal)
            {
                movedImediateHorizontal = true;

            }
            horizontalTimer = 0;

            // Modify position
            transform.position += new Vector3(1, 0, 0);

            // See if valid
            if (isValidGridPos())
            { // It's valid. Update grid.
                updateGrid();
            }
            else
            {    // It's not valid. revert.
                transform.position += new Vector3(-1, 0, 0);
            }
        }

        // Right Rotate
        if (Input.GetKeyDown(KeyCode.O))
        {
            transform.Rotate(0, 0, -90);

            // See if valid
            if (isValidGridPos())
                // It's valid. Update grid.
                updateGrid();
            else
                // It's not valid. revert.
                transform.Rotate(0, 0, 90);
        }
        //Left Rotate
        if (Input.GetKeyDown(KeyCode.I))
        {
            transform.Rotate(0, 0, 90);
            if (isValidGridPos())
                // It's valid. Update grid.
                updateGrid();
            else
                // It's not valid. revert.
                transform.Rotate(0, 0, -90);
        }

        // Move Downwards and Fall
        if (Input.GetKey(KeyCode.S) ||
                 Time.time - lastFall >= 1)
        {
            if (movedImediateVertical)
            {

                if (buttonDownWaitTimer < buttonDownWaitMax)
                {
                    buttonDownWaitTimer += Time.deltaTime;
                    return;
                }


                if (verticalTimer < continuosVerticalSpeed)
                {
                    verticalTimer += Time.deltaTime;
                    return;
                }
            }
            if (!movedImediateVertical)
            {
                movedImediateVertical = true;
            }
            verticalTimer = 0;


            // Modify position
            transform.position += new Vector3(0, -1, 0);

            // See if valid
            if (isValidGridPos())
            {
                // It's valid. Update grid.
                updateGrid();
            }
            else
            {
                // It's not valid. revert.
                transform.position += new Vector3(0, 1, 0);

                // Clear filled horizontal lines
                Grid.deleteFullRows();

                // Spawn next Group

                createRandObjs.Instance.spawnNext();

                // Disable script
                enabled = false;
            }

            lastFall = Time.time;
        }
    }

    // Use this for initialization
    void Start()
    {

    }




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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+2

おそらく、各パートの処理の順序に起因するものと思われます。

現状の順序では、

  • キーを離したときの処理
  • 左移動処理
  • 右移動処理
  • 右回転処理
  • 左回転処理
  • 下移動処理

となっています。このうち、「左移動処理」「右移動処理」「下移動処理」の3つのパートでは、移動スピード調整のためタイマーの値によってreturnでメソッドを抜けるケースがあります。

縦移動中には回転できて横移動中には回転できないという現象があるとのことですが、下移動パートは回転パートの後に位置しているので問題は顕在化しませんが、左右のいずれかの移動キーを押している場合、かなりの確率でタイマー条件に引っかかり、回転パートへ到達せずにメソッドが終了してしまうのが原因ではないでしょうか?

また、落下速度が遅くなる現象についても、同じく途中でメソッドが終了してしまうために落下処理の実行頻度が低下して、落下速度が遅くなったように見えるものと予想されます。

改善案としては、タイマー判定のあるパートでは、タイマー条件が満足されたときにreturnでメソッドを終える代わりに、フラグとなる変数を用意してそれをtrueとすることにし、そのパートの実際の移動処理部分をifで囲って、フラグ変数がfalseの時のみ移動処理が行われるようにする...というのはどうでしょう?
これならメソッドを中断させることなく後ろのパートへも処理を進めさせることができるのではないでしょうか。

[追記]
How to make a game like Tetris in Unity 5 - Part 14 - Increasing Difficultyの冒頭で左右キーを押している間に落下しなくなる問題に言及しており、これに対する処置として、この辺で「左移動」「右移動」「下移動」「回転」パートを別メソッドに分離して独立させています。こちらのスタイルの方がUpdateがシンプルになってよさそうですね。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

  • 受付中

    Unityでのナビゲーションラインの実装について

    unityでナビゲーションラインを実装したいと思っています。 画像中央の青いラインみたいなもの、プレイヤーから特定のオブジェクトに対して線を引き、方向を教える。 現在LineRe

  • 受付中

    Unity2Dで坂をスムーズに上り下りさせたい

    Unity2Dで操作するプレイヤーなどを傾斜のある地面で移動させるとフワッと一瞬だけ空中に浮いてしまうのを何とかしたいのですが 素人なのでよくわからないのですが、接地している地面

  • 解決済

    untiy terrain機能で作った壁が登れてしまう

    unityで、terrainで作った壁を登れなくしたいです。 キャラクターがジャンプ中に移動方向に進むと、terrainで作った急斜面な山や壁を登れてしまいます。 滑り落ち

  • 解決済

    transform.Findでオブジェクトを取得できない

    私の他の質問と同じ内容に関する内容ですが、問題が絞れてきたので、再度質問させて頂きます。 発生している問題・エラーメッセージ カメラに割り当てたスクリプトで、カメラのz座標

  • 受付中

    画面のタッチした場所にオブジェクトを徐々に移動させる(iTween)

    前提・実現したいこと タッチしたところにオブジェクトを徐々に移動させたい 発生している問題・エラーメッセージ タッチしたところに瞬間移動する 該当のソースコード

  • 解決済

    Unityでの線形補間について

    前提・実現したいこと Unity5.6でオブジェクトを持ち、 線形補間で一定間隔スライドさせようとしています。 プレイヤーがオブジェクトを持ち スライドさせるところまで

  • 解決済

    3Dゲームでバイオハザードと同じ様な操作を(自機に)したい。

    ・カメラの位置は自機の頭部の少し後ろ上に固定。 ・カメラのポジションはxとy軸のみ変更可能。 ・W,S,A,Dのそれぞれのキーで前進、後退、左移動、右移動。 上記の三点を行いた

  • 解決済

    カメラ視点をリセットするには?

    カメラの視点をリセットするにはどうすればいいのか教えていただきたいです。 キャラの向きとは別にカメラワークによる上下左右の確認をした後にそのカメラ視点を初期状態ローテーションを(0

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

  • C#

    6549questions

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

  • Unity

    3570questions

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

  • Unity2D

    756questions