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

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

新規登録して質問してみよう
ただいま回答率
85.35%
C#

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

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

3594閲覧

【Unity2D】ロープにしがみついてぶら下がり、振り子のように揺らしてジャンプするようなギミックを作りたい

cushionA

総合スコア90

C#

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

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2020/09/02 16:45

編集2020/09/02 18:28

前提・実現したいこと

ロープにぶら下がってブランコのように動かして、ロープの慣性でジャンプするようなギミックを作りたい。
また、ロープにぶら下がっていて、かつロープに力が加わっていない(揺れていない)状態ではロープ内を上ったり下りできるようにしたい。

発生している問題・エラーメッセージ

ロープとロープを揺らす仕組みを作って、しがみつきと離れる(不備はありますが)ところまではできました。
(以下のリンクはGifのImgerリンクです。それからしがみつきモーションなどはまだ作ってないのでアニメーションが遷移していないのは仕様の範囲内です、すみません)

しかし見ての通りジャンプに不備があります。
コードで意図したとおりに浮き上がらず、勢いのない落ち方をします。

ロープジャンプ1(助走なし)
ロープジャンプ1
ロープジャンプ2(助走あり)
ロープジャンプ2

しがみつく前の速度が影響しているようですが、一応しがみついた際にVelocityはゼロにして、さらにプレイヤーコントローラーを停止して行動関係のフラグなども初期化し、その上速度をロープから離れた際に塗り替えています。

(該当する処理については詳しくはコードの項目で説明させていただきます。すみません)

また、ロープの上り下りの実装もうまくいかないので相談に参りました。

コード全体の仕様について

基本的に移動はRigidBody2DのVelocityを直接いじる形にしてあるので重力などは利用できません。
加速減速の物理的な挙動はAnimationCurveでなるべく再現しています。
これはボタン入力の長さとジャンプの高さを連動できるようにしたかったのでそうしました。
また、ロープをうごかすのはロープの一番上にHingeJoint2Dでつないである部位のMoterによる回転を利用しています。
ジャンプなどができたらロープにしがみつき中に横キーで任意の方向にロープを動かせるようにするつもりです。

該当のソースコード

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class GimmickAct : MonoBehaviour 6{ 7 //プレイヤーオブジェクトの子オブジェクトの判定用のオブジェクトにアタッチする 8 //ギミック利用可能か、またギミックを利用中かを判定するスクリプト 9 10 [HideInInspector] public bool isGimmickOn; 11 //ギミック利用中のフラグ。これが立っているとプレイヤーコントローラーのあらゆるアクションが不可能になる 12 //またisDashやisJumpなどのあらゆるフラグがfalseされてアクションの計測されていた持続時間等も白紙にしたうえでreturnするように 13 //プレイヤーコントローラーを停止してギミック側の処理でプレイヤーを動かすことでいろんなギミックに対応できるようにしたかった 14 15 bool isGimmick; 16 //接地判定と似たようなギミック利用可能かどうかのフラグ 17 18 bool isGimmickEnter; 19 bool isGimmickStay; 20 bool isGimmickExit; 21 string gimmickTag = "Gimmick"; 22 //Gimmickタグのオブジェクトの接触を検知する 23 bool isPush; 24 25 26 private void Update() 27 { 28 //ボタンが押されているかどうかの確認 29 30 if (Input.GetButtonDown("Submit")) 31 { 32 33 isPush = true; 34 } 35 else 36 { 37 isPush = false; 38 39 } 40 41 } 42 void FixedUpdate() 43 { 44 if (isGimmickEnter || isGimmickStay) 45 { 46 isGimmick = true; 47 //ギミック利用可能 48 } 49 else if (isGimmickExit) 50 { 51 isGimmick = false; 52 //ギミック利用不可能 53 } 54 isGimmickEnter = false; 55 isGimmickStay = false; 56 isGimmickExit = false; 57 //次の判定まで初期化 58 59 if (isGimmick && isPush && !isGimmickOn) 60 { 61 //ギミック利用可能でボタンが押されていて、ギミック利用中でなければ以下の処理。ギミック利用開始 62 isGimmickOn = true; 63 isPush = false; 64 //ボタンを押されてないことにすることで誤反応を起こすのを防いだ 65 } 66 else if (isGimmickOn && isPush) 67 { 68 //ギミック利用中にボタンが押されたら以下の処理。ギミック利用停止 69 isGimmickOn = false; 70 isPush = false; 71 } 72 } 73 74 private void OnTriggerEnter2D(Collider2D collision) 75 { 76 //ギミックを利用可能か判定 77 if (collision.tag == gimmickTag) 78 { 79 isGimmickEnter = true; 80 } 81 } 82 83 private void OnTriggerStay2D(Collider2D collision) 84 { 85 if (collision.tag == gimmickTag) 86 { 87 isGimmickStay = true; 88 89 } 90 91 } 92 private void OnTriggerExit2D(Collider2D collision) 93 { 94 if (collision.tag == gimmickTag) 95 { 96 isGimmickExit = true; 97 } 98 } 99} 100

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class RopeJump : MonoBehaviour 6{ 7 //ロープにアタッチするジャンプ用のスクリプト 8 9 10 public GameObject Player; 11 //プレイヤーオブジェクトを取得 12 13 PlayerMove pm;//プレイヤーコントローラーのスクリプト 14 Rigidbody2D rb;//プレイヤーオブジェクトのRigidBody2D 15 Rigidbody2D myRb;//自分のRigidBody2D 16 Vector2 box;//Velocity変更のための構造体の入れ物 17 Transform tf;//プレイヤーオブジェクトのトランスフォーム 18 string playerTag = "Player";//プレイヤーオブジェクトのタグ 19 bool isFly;//プレイヤーオブジェクトがギミック利用可能範囲内に来たかどうかを判断する。trueならFlyできるという意味 20 bool isGrip;//ロープにしがみついているかどうか 21 bool isPush;//ボタンを押しているかどうか 22 23 24 // Start is called before the first frame update 25 void Start() 26 { 27 pm = Player.GetComponent<PlayerMove>(); 28 rb = Player.GetComponent<Rigidbody2D>(); 29 tf = Player.GetComponent<Transform>(); 30 myRb = GetComponent<Rigidbody2D>(); 31 //変数に上記の通りのものを格納 32 } 33 34 // Update is called once per frame 35 void Update() 36 { 37 if (Input.GetButtonDown("Submit")) 38 { 39 isPush = true; 40 //前と同じボタン処理 41 } 42 else 43 { 44 isPush = false; 45 } 46 } 47 private void OnTriggerEnter2D(Collider2D collision) 48 { 49 //プレイヤーオブジェクトがトリガーの範囲内に来たかどうか判定 50 //一度範囲内にきて起動したら動作終了までtrueにするので再判定については考えていない 51 if (collision.tag == playerTag) 52 { 53 isFly = true; 54 } 55 } 56 57 private void FixedUpdate() 58 { 59 if (isFly) 60 { 61 //ギミック起動 62 if (!isGrip && isPush) 63 { 64 //ロープにしがみついていなくて、ボタンが押されたら以下の処理 65 66 //ロープ下端にジョイントされたオブジェクトの子オブジェクトに 67 Player.transform.parent = this.gameObject.transform; 68 //ローカルポジションはゼロにして 69 Player.transform.localPosition = new Vector3(0, 0, 0); 70 //親オブジェクトに連動するようにRigidBody2Dのタイプを変える 71 rb.bodyType = RigidbodyType2D.Kinematic; 72 //そしてしがみつきのフラグをtrueにして 73 isGrip = true; 74 //誤作動防止のためにボタンは押してないことに 75 isPush = false; 76 } 77 78 //握っていてボタンが押されたら飛ぶ 79 if (isGrip && isPush) 80 { 81 //握っていない 82 isGrip = false; 83 //isFlyをfalseに 84 //そして再度Enterしない限りこのスクリプトは再びisFlyはtrueになれない。 85 //よってジャンプしてすぐ別のギミックのためにボタンを押しても誤作動しない 86 isFly = false; 87 88 //親子関係を解消 89 Player.transform.parent = null; 90 //プレイヤーオブジェクトを直立させる 91 Player.transform.rotation = new Quaternion(0, 0, 0,0); 92 //プレイヤーオブジェクトをプレイヤーコントローラーを通じて強制的にジャンプさせる 93 pm.isJump = true; 94 //RigidBody2Dのタイプを元に戻す 95 rb.bodyType = RigidbodyType2D.Dynamic; 96 //ロープのVelocityを格納 97 box = myRb.velocity; 98 //プレイヤーオブジェクトにVelocityを与える。 99 //これによりプレイヤーオブジェクトがロープの勢いをそのままに跳躍することを意図しました 100 rb.velocity = box; 101 //一応誤作動阻止 102 isPush = false; 103 } 104 } 105 } 106 }

C#

1 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine; 5using HutongGames.PlayMaker; 6 7public class PlayerMove : MonoBehaviour 8{ 9 //プレイヤーコントローラースクリプトを抜粋 10 11 bool isStop;//プレイヤーコントローラー停止フラグ。 12         //ほかの変数は割愛 13 14//Updateで入力、Startで初期化 15 16 void FixedUpdate() 17 { 18 if (ga.isGimmickOn) 19//コントローラー停止フラグの発動条件。後々増えるかもしれないのでこういった形に 20 { 21      //停止すべきかどうか判定 22 isStop = true; 23 } 24 else 25 { 26 isStop = false; 27 } 28 29 if (isStop) 30 { 31      //プレイヤーコントローラー停止フラグが真の時、速度ゼロに 32 rb.velocity = new Vector2(0, 0); 33 34      //以下全行動フラグと判定用の測定した時間を初期化 35      //回避などで変わっているかもしれないレイヤーも定義したメソッドで元に戻しておく 36 isJump = false; 37 isDash = false; 38 isSquat = false; 39 isAvoid = false; 40 isStartRoll = false; 41 at.isAttack = false; 42 dashTime = 0.0f; 43 jumpTime = 0.0f; 44 rushTime = 0.0f; 45 fallTime = 0.0f; 46 47 SetLayer(11); 48 49       //この先の処理は行えない 50       //また、停止中はUpdateの入力も不可能 51 return; 52 } 53 } 54

試したこと

まずジャンプについてですが、AddForce2Dにて射出しようとしたところロープの振れ幅による射出速度の調整ができず断念いたしました。

のぼりおりについてはローカルポジションの移動ですと停止した際にも残るうねりによりロープから離れてしまいました。
親子関係ではなくParent ConstraitやFSliderJointを利用することに活路を求めたものの、これは前者はコードから動かすのが難しかったこと、後者は想定したような使い方ができないようだったので使用をあきらめました。

根本的な移動方法のなどの仕様変更を含むアドバイスも心より歓迎させていただきます。
どうかお力添えよろしくお願いいたします。

追記:ロープののぼりおりについてはロープの各パーツの初期座標を記憶しておく。
そして揺らす力が消えてある程度ロープが落ち着いたところで初期座標を設定して強制的に真っ直ぐにし、まっすぐなロープをlocal positionの変更でよじ登らせるというような方法を今考えつきました。
ロープの当たり判定はトリガーのみなのでおそらく揺れませんので、登るのを揺れてない時だけにすれば離れる心配はありません。
明日試してみます。
しかし登るとき揺れないロープというのはどうなのかということと、うまく行くかわからないのでやはりアドバイスをいただけたら嬉しいです。

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

Unity 2019 3,7f1

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

申し訳ありません、自力での解決は不可能でした。

アセット:2D Rope System

こちらのアセットに付属していたコードを改造して実装しました。
そしてアセットであるがゆえに詳細なコードは貼れません、本当に申し訳ありません。

しかしもし同じところでつまずいた方がいらっしゃいましたら、接触したロープのセグメントの子オブジェクトにして動きを同期する。
そしてセグメントの親オブジェクト伝いにロープのセグメントをすべて上から順にリストに格納して、下キーなどの入力で親オブジェクトを一個下の(上キーなら一個上の)セグメントに変える。
そしてaddForceによりロープを揺らす。
この方法を試してみてください。

個人開発なら使えるものは何でも使うがモットーなのでこのような解決になってしまいました。
質問を出しておきながら自己解決すらまともに記せず申し訳ありません。
ご迷惑をおかけしました。

投稿2020/09/08 12:46

編集2020/09/08 14:25
cushionA

総合スコア90

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問