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

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

ただいまの
回答率

90.52%

  • Unity

    3978questions

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

  • Unity2D

    875questions

UNITY2Dでの落下の停止、再開の切り替えに関わる問題

解決済

回答 2

投稿

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

ITATI

score 4

 前提・実現したいこと

横スクロールアクションで梯子を使う時に落下しないようにしたいと考えています。
Rigidbody2DではUse Gravityが使えないようなので、

ladder = true(梯子オブジェクトに接触)状態時に↑のキーを押す事で、
movement_active を true にし、 
movement_active = true の間は以下の記述で落下を停止。

GetComponent<Rigidbody2D>().velocity = Vector3.zero;
GetComponent<Rigidbody2D>().isKinematic = true;


次回、ジャンプボタンが押された時にmovement_active = falseで

GetComponent<Rigidbody2D>().isKinematic = false;


落下状態を再開するしくみです。

 ソースコード

Player.cs

public class Player : MonoBehaviour {
    bool Lock = true;
    // === キャッシュ ==========================================
    PlayerController playerCtrl;
    void Awake()
    {
        playerCtrl = GetComponent<PlayerController>();
    }
    void Update()
    {

        // 操作可能か?
        if (!playerCtrl.activeSts) { return; }
        // パッド処理
        float joyMvX = Input.GetAxis("Horizontal");
        float joyMvY = Input.GetAxis("Vertical");
        playerCtrl.Horizontal_Move(joyMvX);
        playerCtrl.Vertical_Move(joyMvY);

        if (Input.GetButtonDown("Jump"))// ジャンプ
        {
            playerCtrl.ActionJump();
            return;
        }

        if (joyMvY > 0)
        {
            playerCtrl.Movement_Object();
        }
        if (joyMvY < 0 & !(Input.GetButtonDown("Jump") ))
        {
            playerCtrl.Movement_Object();
        }
        //省略
    }


PlayerController.cs

public class PlayerController : BaseCharacterController
{
// === 外部パラメータ(インスペクタ表示) =====================
public float initHpMax = 20.0f;
public float moveSpeed;
[Range(0.1f, 100.0f)] public float initSpeed = 5.0f;
public float Jumphight = 14.0f;
public float Rayoutput1 = 0.0f;

// === 内部パラメータ ======================================
public int jumpCount = 0;
bool breakEnabled = true;
float groundFriction = 0.0f;
// === コード(Monobehaviour基本機能の実装) ================
    protected override void Awake()
    {
        base.Awake();

        // パラメータ初期化
        speed = initSpeed;
        SetHP(initHpMax, initHpMax);
    }
    public void ActionJump()
    {
        ladder_active = false;
        stair_active = false;
        movement_active = false;

        switch (jumpCount)
        {
            case 0:
                if (grounded)// 地面に接触した状態でのジャンプ
                {
                    animator.SetTrigger("Jump");
                    GetComponent<Rigidbody2D>().velocity = Vector2.up * Jumphight;
                    jumpStartTime = Time.fixedTime;
                    jumped = true;
                    jumpCount++;
                }
                else if (!grounded)// // 空中にいてジャンプを行っていない場合
                {//省略}
            case 1:
                if (!grounded)// 地面に接触していない状態
                {
                    animator.Play("Player_Jump", 0, 0.0f);
                    GetComponent<Rigidbody2D>().velocity = new Vector2(GetComponent<Rigidbody2D>().velocity.x, Jumphight);
                    jumped = true;
                    jumpCount++;
                }
                break;
        }
}
    public void Movement_Object() {
        if (ladder == true){ladder_active = true; movement_active = true;};
        if (stair == true){ stair_active = true; movement_active = true; };
         if (true)//はしご状態時等に重力を無効化
         {
         GetComponent<Rigidbody2D>().velocity = Vector3.zero;
         GetComponent<Rigidbody2D>().isKinematic = true;
         }
        else if (movement_active == false)//通常時に重力を有効化
        {
        GetComponent<Rigidbody2D>().isKinematic = false;
        }
}

 発生している問題

1.落下の停止は成功しますが、その後ジャンプボタンを押しても落下が解除されず、
壁を貫通したうえで上昇してしまいます。
GetComponent<Rigidbody2D>().isKinematic = false;
が効いていないものと思われますが、画像の様にインスペクター上は
movement_activeのチェックがfalseに解除されています。
イメージ説明

2.movement_active を true なった瞬間に、
前方入力以外を受け付けなくなる時間が0.5秒程あるようです。
おそらくPlayer.csのif (joyMvY > 0){playerCtrl.Movement_Object();}が上を押している間常に稼働している
のではないかと予想しますが、実際の切り替え動作はPlayerController.csでmovement_activeの切り替えを行わせている為に解決策が思いつきませんでした。

この2つの問題に関わるエラーメッセージは発生していません。
何か解決策があればご教示お願い致します。 

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

Unity 2018.1.1f1

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+1

Kinematicなオブジェクトは衝突判定の特性が変わるので、「重力を無効化しつつ物理演算を残す」だけなら「Gravity Scale」を0にする方が正しい演算になるのではないかと思います。
Rigidbody 2D - Unity マニュアル

それはそれとして、落下が解除されないのはMovement_Object()内で
if (true)//はしご状態時等に重力を無効化となっているので常に重力無効化状態になっているからかと。

入力を受け付けない時間があるのは恐らく
GetComponent<Rigidbody2D>().velocity = Vector3.zero;
の影響で、通常移動で発生させた速度を打ち消しているのではないかと思います。
(つまり意図せずif (true)//はしご状態時等に重力を無効化の方に入ってしまっている)

あとこれはバグと関係ないですが、GetComponent<Rigidbody2D>()は負荷があるので変数にした方がいいです(今は作業途中かもしれませんが)。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/07/02 23:02

    アドバイスありがとうございます。
    GetComponent<Rigidbody2D>()をそのまま使うと負荷があるというのは教本では確認できず、初めて知りました。

    GetComponent<Rigidbody2D>().velocity = Vector3.zero;
    を削除すると確かに操作不能状態がなくなることを確認しました。
    ただ、これを外すと梯子状態でのY軸固定が出来ず、落下してしまいます。

    いくつかミスを修正しましたが、落下が解除されない問題は解決しませんでした。一番ましな動作が、以下のソースでした。
    質問のGIF動画の症状とほぼ同じですが、壁を貫通せず上昇中に上を押すと重力が戻って落下を始めるというものです。

    Rigidbody2D RB;
    awake関数に RB = GetComponent<Rigidbody2D>();追加
    ```
    if (movement_active == true)//はしご状態時等に重力を無効化
    {
    RB.velocity = Vector3.zero;
    RB.gravityScale = 0;
    }
    if (movement_active == false)//通常時に重力を有効化
    {
    RB.gravityScale = 4;
    }
    ```
    Movement_Object関数で↑キーを押すと一回動作するというのが原因と思われるので、
    if (movement_active == false)以下をupdate関数に移動してみましたが、これでは重力が復帰しませんでした。

    キャンセル

  • 2018/07/03 18:26

    要所要所に Debug.Log();を仕掛けてRB.velocity、RB.gravityScale、movement_active値が希望通りの値になっているか確認してみてください。

    RB.velocityは本来自動計算される値なので、例えば重力がオフの状態で
    RB.velocity = Vector3.up;
    と一度どこかで指定したら、何かにぶつかるかスクリプトで止めるまでその速度で動き続けます。

    重力がオンの状態でも、Update等の常に呼び出されるスクリプト内でvelocityを指定していた場合、重力を上書きする形で指定した方の速度が適用されます(どっちが適用されるかはタイミングによる。「UpdateとFixedUpdateの違い」を調べてみると良いかと)。
    この辺りで予期しない動きになってはいないでしょうか。

    キャンセル

  • 2018/07/03 23:25

    解決しました。public void Movement_Object()関数部分に細かい動作(落下停止、解除)の指定をしていたのが原因です。
    public void Movement_Object()関数部分ではtrue、falseの指定のみ記述して、細かい動作指定はFixedUpdate関数部分に記述した所正常に動作しました。解決にした部分のソースを追記しました。
    ご協力いただき、有難う御座いました。

    キャンセル

0

public class PlayerController : BaseCharacterController
{
// === 内部パラメータ ======================================
Rigidbody2D RB;
protected override void Awake()
    {
        base.Awake();
        // パラメータ初期化
        speed = initSpeed;
        SetHP(initHpMax, initHpMax);
        RB = GetComponent<Rigidbody2D>();
    }


protected override void FixedUpdateCharacter()
    {
        // 着地チェック
        // キャラの方向
        // ジャンプ中の横移動減速
        // 移動停止(減速)処理
        if (ladder_active == true && air == true)
        {
            Vector3 Object_pos = transform.position;
            Object_pos.x = Object_posX;//はしご用の座標調整
            transform.position = Object_pos;
            speedVx = 0;
        }

        if (movement_active == true)//はしご状態時等に重力を無効化
        {
            RB.velocity = Vector3.zero;
            RB.gravityScale = 0;
        }
        if (movement_active == false)//通常時に重力を有効化
        {
            RB.gravityScale = 4;
        }

    }


public void Movement_Object()//↑キーを押したときに一度反応
    {
        if (ladder == true){ladder_active = true; movement_active = true; jumpCount = 0; };
        if (stair == true){ stair_active = true; movement_active = true; jumpCount = 0; };
    }

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

  • 解決済

    Unityでベルトコンベア作りたい

    前提・実現したいこと Unityでベルトコンベア上を走り障害物を躱してゴールを目指すゲーム 発生している問題・エラーメッセージ ベルトコンベア上の物体(障害物・Playe

  • 解決済

    MissingComponentExceptionのエラー

    MissingComponentException: There is no 'Rigidbody2D' attached to the "Cube" game object, b

  • 解決済

    自キャラが向いてる方向に攻撃をしたい

    3Dゲームの自機にビームの様な攻撃をしたいのですが真っすぐ(Z軸)にしか弾が飛んでいきません。 自機が向いてる方向に攻撃を行うにはどの様なコードを記述すればいいのか教えて頂きたいで

  • 解決済

    【unity】何故このスプリクトが2段回ジャンプになるのか?

    プレイヤーのジャンプのスクリプトについて質問です。 プレイヤーを1段階ジャンプと2段階ジャンプで分けようと思って、1段階ジャンプのスクリプトを書いたつもりなのですが、何故だか2段階

  • 解決済

    Unityで頂点を散らばしたものをゆっくり元の形に戻す方法

    以下がオブジェクトにアタッチするスクリプトです。 開始と同時に点となって散らばってるんですが、 Invoke()関数を使って10秒後に戻そうと思ってるのですが、 散らばったままで動

  • 解決済

    ゲームが終了した時GameOverにならない

    【Unity5】uGUIでタイトルとゲームオーバー画面を実装!Canvas, Text, Button【フラッピーバード風5】 ↑ こちらのサイトを参考にIsTriggerがOFに

  • 解決済

    Unity 移動している方向に球を回転させたい

    Unityで球を移動している方向(rigidbodyのvelocity)に回転をさせたいのですが、今一やり方がわかりません。 どの様な感じにすればいいのでしょうか?よろしくお願いし

  • 解決済

    isTriggerをスクリプトで変更したい

    unity isTrigger チェックボックスをスクリプトで切り替え (c# 上記の質問を参考にしてisTriggerを変更するスクリプトを書きました。 しかし、エラーが3種類出

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

  • Unity

    3978questions

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

  • Unity2D

    875questions