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

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

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

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

スクロール

スクロールとは、ディスプレイスクリーン上において連続的にコンテンツが滑っていくことを指します。

Unity

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

Q&A

解決済

3回答

6880閲覧

Unity縦スクロール障害物競争で、加速アイテムを取ったあと元の速さに戻るようにしたい

Kageyama_23457

総合スコア21

C#

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

スクロール

スクロールとは、ディスプレイスクリーン上において連続的にコンテンツが滑っていくことを指します。

Unity

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

0グッド

0クリップ

投稿2020/01/09 13:06

編集2020/01/12 07:55

Unity縦スクロール障害物競争で、加速アイテムを作りたい

Unity、C#ともに初心者なので、至らぬ点あるかと思いますがご容赦ください。
Unityの3Dモードで、縦スクロールの、障害物競争のようなゲームを作っています。
具体的に書くと、「自機キャラがいて、他に3人ほどCPUがいて、ゴールを目指す。
途中、①障害物(当たり判定使用)、②加速アイテム(一定時間速くなる)、そして③アビリティアイテムがある。
アビリティアイテム→取るととそのキャラごとの必殺技が使えて、他キャラへの妨害などができる。
CPUも障害物を避けたり加速アイテムやアビリティアイテムを狙ってきたりする。」といったところです。

この度は加速アイテムについて質問致します。
まず、「unity 加速装置」と検索して出る講座ページの「加速パネル(踏んづけて加速)」ではダメだったので、
「加速アイテム(ゲットして加速)」にしました。

↓playerスクリプトまるごと

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class player : MonoBehaviour 6{ 7 public float speed;//インスペクタで速度をいじくる宣言 8 9 private Animator anim = null; 10 private Rigidbody2D rb = null;//アニメとRBの変数宣言 11 12 private string ochaTag = "Ocha";//★お茶タグを宣言 13 14 void Start() 15 { 16 anim = GetComponent<Animator>(); 17 rb = GetComponent<Rigidbody2D>();//インスタンスを取得命令 18 } 19 20 // Update is called once per frame 21 private bool isKasoku = false;//★加速boolを宣言、通常は加速してないよ(お茶を取ってないよ) 22 void FixedUpdate() 23 { 24 float verticalKey = Input.GetAxis("Vertical");//上下キー宣言 25 float horizontalKey = Input.GetAxis("Horizontal");//左右キー宣言 26 float ySpeed = 0.0f;//y軸移動速度の初期値 27 float xSpeed = 0.0f;//x軸移動速度の初期値 28 if(verticalKey<0)//下キーが押されたら(上に行く必要がないゲームなので下キーのみ指定しています) 29 { 30 anim.SetBool("run", true);//アニメon 31 ySpeed = -speed;//走る 32 } 33 else 34 { 35 anim.SetBool("run", false);//アニメoff 36 ySpeed = 0.0f;//走らない 37 } 38 39 if(horizontalKey>0)//右キーが押されたら 40 { 41 xSpeed = speed;//右に行く 42 } 43 else if(horizontalKey<0)//左キーが押されたら 44 { 45 xSpeed = -speed;//左に行く 46 } 47 rb.velocity = new Vector2(xSpeed, ySpeed);//上記の記述をこの式に代入して動いているそうですがよくわかってません。 48 49 if(isKasoku==true)//★加速フラグがtrueの場合の挙動 50 { 51 rb.velocity = new Vector2(xSpeed,ySpeed*4);//★y軸移動速度が4倍になる(今後通常時の走行速度の違う他キャラも増やすので、この方が汎用性があります) 52 } 53 else if(isKasoku==false)//★加速フラグがfalse、つまり通常時 54 { 55 rb.velocity = new Vector2(xSpeed, ySpeed);//★通常時と同じ速度を記述 56 } 57} 58 private void OnCollisionEnter2D(Collision2D collision)//★(お茶との)衝突判定 59 { 60 if(collision.collider.tag==ochaTag)//★お茶タグとぶつかったら 61 { 62 isKasoku = true;//★加速フラグがtrueになるよ 63 Destroy(collision.gameObject);//お茶が消えるよ 64 } 65 } 66} 67//アイテムによる加速までできた。

今困っているのは、加速したあと元の速さに戻せないことです。
例:5秒間、走る速さが4倍になる。その後は元の速さで走る(キャラクターごとに元の走る速さは違います)
というふうにしたいです。

試したこと

・コルーチンが正解かと思い、上記スクリプトにねじ込もうとしました。

###エラー、メッセージ
以下、上記スクリプトにコルーチンをねじ込んだ部分を抜粋

C#

1 void Start() 2 { 3 anim = GetComponent<Animator>(); 4 rb = GetComponent<Rigidbody2D>();//インスタンスを取得命令 5 StartCoroutine("Kasoku"); 6 } 7 IEnumerable Kasoku() 8 { 9 rb.velocity = new Vector2(xSpeed, ySpeed * 4); 10 11 yield return new WaitForSeconds(5) 12 13 //ここに「元の速度に戻る」と書くべきだと思うのですが、書き方がわかりません。 14 }

①この質問ページでは見えませんが、VisuialStdioにおいてxSpeedとySpeedに赤線が引かれ、
「現在のコンテキストに(xSpeed/ySpeed)という名前は存在しません」と出ます。
playerスクリプト内で定義(?)していると思うのですがだめなのでしょうか。
②スクリプト内にも書きましたが、元の速度に戻るという命令の書き方がわかりません。
丸投げ状態で申し訳ないのですがご教授頂きたく存じます。

★playerスクリプトですが、上記のものはvelocityで動かしていますが、アドバイスを頂きAddForceで動くものも作りました。
今回はvelocityのものを載せましたが、AddForceの方が加速と減速の問題が解決しやすいならそちらにしますのでお教え頂きたいです。

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

■作業環境
Mac Sierra10.12.6(8GB)
Unity2018 4.14f1

■ここまで出来ていること
・キャラクターのアニメーション実装、及び下キー入力によるアニメ遷移
(待機時:歩いている→下キー入力:走る(手足の動きが早くなる))
・キャラクターの下と左右の移動。上に行く必要はないので、上キーを入力しても動きません。
・カメラのプレイヤー追従(y軸)
・障害物の設置(キャラと障害物に当たり判定をつけた)
・CPUキャラの自走(y軸下に向けて進むだけですが)
・一応、加速アイテムを取って加速しっぱなしの映像を貼っておきます。
(とあるマンガの非営利二次創作で、拙い絵でお恥ずかしいのですがスルーお願いします)
https://streamable.com/p6esx

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

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

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

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

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

guest

回答3

0

ベストアンサー

【修正2020/01/16】スクリプトを修正しました、変更点は移動の定義を個別に分け、加速度や加速時間をインスペクターから変更できるように追加しておきました。
個人的な感想ですが、加速時間5秒は体感的に長かったので3秒ぐらいでいいかもしれません。


やるとしたらアイテム取得時に加速度フラグを4秒間Trueにして4秒たったらFalseにすればいいと思いますが、その切り替えをFixedUpdateの中に書いているのはよくありません。
何故かというと、これは条件を満たしている時に常に適応されるので、加速度フラグがFalseの時、毎フレーム「rb.velocity = new Vector2(xSpeed, ySpeed);」「rb.velocity = new Vector2(xSpeed, ySpeed);」「rb.velocity = new Vector2(xSpeed, ySpeed);」...と繰り返されていることになります。

それを踏まえた上での改変を行います。
あと①の質問に対する回答ですが、C#の変数にはスコープ({}←これ)と呼ばれる機能があり、スコープの外側で宣言された変数は内側のスコープでも使用可能ですが、異なるスコープで宣言されている変数は別のスコープ内では使えない決まりがあります。
そのため、何回も使用する変数は一番最初にclass内で宣言し、各メソッド内部で使用できるようにします。

更に老婆心ながらスクリプト内に「上記の記述をこの式に代入して動いているそうですがよくわかってません。」と書いてあったので、何をやってるか説明すると、
float verticalKey = Input.GetAxis("Vertical");//上下キー宣言
float horizontalKey = Input.GetAxis("Horizontal");//左右キー宣言
の二行でキーの入力値を取得し、if(verticalKey < 0)で入力値が0以下の場合は-の速度を渡し、0以上の場合は+の速度を渡す、という事をしています。
横も同じ、決まった値をrb.velocity = new Vector2(xSpeed, ySpeed);に渡すことで移動してます。

あとIEnumerableIEnumeratorは似てますが、全く異なるので注意してください。
コルーチンで使うときはIEnumeratorです。

以下スクリプト、多分これで動作すると思います。しなかったらコメントしてください。

cs

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class player : MonoBehaviour 6{ 7 public float Speed;//インスペクタで速度をいじくる宣言 8 public float KasokuSpeed = 1;//インスペクターでお好みの加速値を決めてください、0にすると移動しなくなるので1以上の値にしてください。 9 public int KasouTime = 1;//インスペクターでお好みの倍速にする時間を決めてください、0にすると加速しなくなるので1以上の値にしてください。 10 private float ySpeed = 0.0f;//y軸移動速度の初期値 11 private float xSpeed = 0.0f;//x軸移動速度の初期値 12 private float verticalKey; 13 private float horizontalKey; 14 private Animator anim = null; 15 private Rigidbody2D rb = null;//アニメとRBの変数宣言 16 private string ochaTag = "Ocha";//★お茶タグを宣言 17 private bool isKasoku = false;//★加速boolを宣言、通常は加速してないよ(お茶を取ってないよ) 18 19 void Start() 20 { 21 anim = GetComponent<Animator>(); 22 rb = GetComponent<Rigidbody2D>();//インスタンスを取得命令 23 } 24 25 void FixedUpdate() 26 { 27 verticalKey = Input.GetAxis("Vertical");//上下キー宣言 28 horizontalKey = Input.GetAxis("Horizontal");//左右キー宣言 29 ChangeSpeed(); 30 } 31 32 void ChangeSpeed() 33 { 34 if(verticalKey < 0)//下キーが押されたら(上に行く必要がないゲームなので下キーのみ指定しています) 35 { 36 anim.SetBool("run", true);//アニメon 37 ySpeed = -Speed;//走る 38 } 39 else 40 { 41 anim.SetBool("run", false);//アニメoff 42 ySpeed = 0.0f;//走らない 43 } 44 45 if(horizontalKey > 0)//右キーが押されたら 46 { 47 xSpeed = Speed;//右に行く 48 } 49 else if(horizontalKey < 0)//左キーが押されたら 50 { 51 xSpeed = -Speed;//左に行く 52 }else if(horizontalKey == 0) 53 { 54 xSpeed = 0f; 55 } 56 57 if(isKasoku==true)//★加速フラグがtrueの場合の挙動 58 { 59 rb.velocity = new Vector2(xSpeed,ySpeed * KasokuSpeed);//★y軸移動速度が4倍になる(今後通常時の走行速度の違う他キャラも増やすので、この方が汎用性があります) 60 } 61 else if(isKasoku==false)//★加速フラグがfalse、つまり通常時 62 { 63 rb.velocity = new Vector2(xSpeed, ySpeed);//★通常時と同じ速度を記述 64 } 65 } 66 67 IEnumerator Kasoku() 68 { 69 isKasoku = true;//★加速フラグがtrueになるよ 70 yield return new WaitForSeconds(KasouTime); 71 isKasoku = false; 72 } 73 private void OnCollisionEnter2D(Collision2D collision)//★(お茶との)衝突判定 74 { 75 if(collision.gameObject.tag == ochaTag)//★お茶タグとぶつかったら 76 { 77 StartCoroutine(Kasoku()); 78 Destroy(collision.gameObject);//お茶が消えるよ 79 } 80 } 81}

投稿2020/01/15 08:30

編集2020/01/16 08:23
Y0241-N

総合スコア1066

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

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

Kageyama_23457

2020/01/15 09:55

Y0241-N様 質問外のことまでご丁寧にありがとうございます。ですが、出していただいたスクリプトを丸コピでくっつけてみたのですが、以下の不具合が生じます。 ・下移動は問題ないが、左右移動は一度キーを押すと、右なら右へ左なら左へ移動しっぱなしになる ・加速アイテムを取っても加速しない
Y0241-N

2020/01/16 01:24

見直しと実際にテストしたところ色々とミスがありましたので、修正しました。 左右に移動し続ける理由はif(horizontalKey == 0)のキー入力がされていない場合の記述がないので、一度入力されたらその方向に移動し続けるようになります。 加速アイテムを取っても加速しない理由は、厳密には加速の命令は通っていますが、FixedUpdate内の移動命令に瞬時に上書きされてしまうので、スピードが変わっていませんでした。
Kageyama_23457

2020/01/16 08:15

できました!! ご丁寧にお手元でのテストや動作しない原因までご教授ありがとうございました。
Y0241-N

2020/01/16 08:23

一部編集中にコメントアウトした箇所とTag名を変更したままだったので修正しました。
guest

0

上記の通りです。投稿時は「加速できない」が問題でそれを自己解決しましたが、別の問題が生じたので未解決に戻し、この欄も削除しました(上記に統合しました)。

投稿2020/01/11 07:51

編集2020/01/12 07:43
Kageyama_23457

総合スコア21

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

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

0

Rigidbody2D .AddForceで使われているForceMode2Dでは、理由は分かりませんがForceMode2D.VelocityChangeが実装されていません。上記のエラーはおそらくそこが原因かと思います。
加えてRigidbody2Dに対して3Dベクトルを扱っているVecter3になっているのでVecter2Dに書き換えます。多分これで動作するのではないかと思います。

(一応仮としてForceMode2D.Impulseにしていますが、質量無視で力を加えたい場合はこことかが参考になるかと。)

c#

1 2void OnTriggerEnter2D (Collider2D other) 3{ 4 other.gameObject.GetComponent<Rigidbody2D> ().AddForce (new Vector2 (0, -30), ForceMode2D.Impulse); 5 Debug.Log ("当たったオブジェクト: " + other.gameObject.name); 6}

いつの間にか質問が変わっていたので追記編集。
コルーチンでの回答がすでにあるのでTime.deltaTimeでのやり方です。
加えて宣言部の調整と、加速の値を変数で管理するよう変更しました。

C#

1public class player : MonoBehaviour 2{ 3 public float speed; //インスペクタで速度をいじくる宣言 4 5 private Animator anim = null; 6 private Rigidbody2D rb = null; //アニメとRBの変数宣言 7 8 private string ochaTag = "Ocha"; //★お茶タグを宣言 9 10 private bool isKasoku = false; //★加速boolを宣言、通常は加速してないよ(お茶を取ってないよ) 11 12 float ySpeed = 0.0f; //y軸移動速度の初期値 13 float xSpeed = 0.0f; //x軸移動速度の初期値 14 15 float verticalKey; //上下キー宣言 16 float horizontalKey; //左右キー宣言 17 18 int DashSpeed; //加速時倍率 19 20 float DashtTime; //加速経過時間 21 22 void Start () 23 { 24 anim = GetComponent<Animator> (); 25 rb = GetComponent<Rigidbody2D> (); //インスタンスを取得命令 26 } 27 28 void FixedUpdate () 29 { 30 verticalKey = Input.GetAxis ("Vertical"); 31 horizontalKey = Input.GetAxis ("Horizontal"); 32 33 if (verticalKey < 0) //下キーが押されたら(上に行く必要がないゲームなので下キーのみ指定しています) 34 { 35 anim.SetBool ("run", true); //アニメon 36 ySpeed = -speed; //走る 37 } 38 else 39 { 40 anim.SetBool ("run", false); //アニメoff 41 ySpeed = 0.0f; //走らない 42 } 43 44 if (horizontalKey > 0) //右キーが押されたら 45 { 46 xSpeed = speed; //右に行く 47 } 48 else if (horizontalKey < 0) //左キーが押されたら 49 { 50 xSpeed = -speed; //左に行く 51 } 52 else //どちらも押されていなければ 53 { 54 xSpeed = 0; //左右に動かない 55 } 56 57 if (isKasoku == true) //★加速フラグがtrueの場合の挙動 58 { 59 DashSpeed = 4; //4倍 60 DashtTime += Time.deltaTime; //フレーム事の経過時間を加算 61 62 //5秒間経過したら 63 if (DashtTime > 5.0f) 64 { 65 isKasoku = false; 66 } 67 } 68 else if (isKasoku == false) //★加速フラグがfalse、つまり通常時 69 { 70 DashSpeed = 1; //等倍 71 } 72 73 rb.velocity = new Vector2 (xSpeed, ySpeed * DashSpeed); //上記の記述をこの式に代入して動いているそうですがよくわかってません。 74 75 } 76 private void OnCollisionEnter2D (Collision2D collision) //★(お茶との)衝突判定 77 { 78 if (collision.collider.tag == ochaTag) //★お茶タグとぶつかったら 79 { 80 isKasoku = true; //★加速フラグがtrueになるよ 81 DashtTime = 0; //加速経過時間リセット 82 Destroy (collision.gameObject); //お茶が消えるよ 83 } 84 } 85} 86//アイテムによる加速までできた。

投稿2020/01/10 01:11

編集2020/01/16 00:39
simapiko

総合スコア332

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

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

Y0241-N

2020/01/10 01:24 編集

横やりすいませんが、これだとForceModeの部分でエラーが出てしまいます。 ForceMode2Dにしたらエラー消えました
simapiko

2020/01/10 01:29

指摘ありがとうございます。コンパイル通していなかったので単純に確認不足でした。修正しました。
Kageyama_23457

2020/01/10 08:44

お二人様ともありがとうございます。 ですが、動作しませんでした。 3Dキューブでダメで、加速パネル画像でもダメでした。 simapiko様が貼ってくださったリンク先も見て、 Vector2(0, -30*9) (9=キャラのRigidbody2DのMassの小数点以下切り捨て) と書いてみましたがこれもダメでした。 いずれもエラーは出ませんが、キューブを貫通してすり抜けるだけです。 こちらのやり方が何かまずいのかもしれませんが…… よろしければまたご教授頂けると幸いです。
simapiko

2020/01/10 09:57

OnTriggerEnterを2Dに変更するのが抜けていたので、修正しました。 3Dオブジェクトと2Dオブジェクトでは接触判定が取れなかったはずなので、加速オブジェクトを2DColliderにして試してみてください。
Kageyama_23457

2020/01/10 10:23

頂いたスクリプト試しましたが、加速しませんでした。 デバッグに接触したというメッセージは出ました。 加速が一瞬すぎて見逃している、ということは多分ないとは思うのですが、 動画を撮りましたのでご覧頂けると幸いです。 (とあるマンガの非営利二次創作で、拙い絵で恥ずかしいのですがスルーしてください) https://streamable.com/wqh0n
Kageyama_23457

2020/01/11 07:56

上記の通り自己解決致しました。お二人様ともありがとうございました!
simapiko

2020/01/11 10:44

返信遅くなりすみません、自己解決できたみたいでよかったです。 コード拝見させていただいたのですが、加速後にPlayerスクリプトのvelocityで速度上書きされているのが原因っぽそうですね。
Kageyama_23457

2020/01/11 11:16

>>simapiko様 ごめんなさい、知識不足で何の原因かすらわかりません。これまでIsTriggerでだめだったことでしょうか?
simapiko

2020/01/11 13:04 編集

IsTriggerはあまり関係ないです。 Playerスクリプトのrb.velocityでオブジェクトの「速度」を指定しています。対して、kasokuのAddForceではオブジェクトに「力」を加えています。 オブジェクトにどれだけ大きな「力」を加えても、その後に「速度」が指定されてしまえば、動く速度はその指定された速度にしかなりません(ほんの一瞬だけ動くとかはあるかもしれませんが)。 動作しなかった原因は、加速アイテムに接触→AddForceで「力」を加える→velocityでySpeedに「速度」を書き換えるのような感じでySpeedを超えるような事はないと考えられます。
simapiko

2020/01/11 11:55

また、速度を直接操作しているので効果が切れた場合、加速時の速度から通常時の速度に急に切り替わります。物理的挙動の減速をしたい場合は少し工夫する必要があります。
Kageyama_23457

2020/01/11 12:23

↓playerスクリプトのこの行でしょうか? rb.velocity = new Vector2(xSpeed, ySpeed);//上記の記述をこの式に代入して動いているそうですがよくわかってません。 上記playerスクリプトから加速アイテム(お茶)関係をなくして、かつこの行もなくしたスクリプトを作って、kasokuスクリプトをお茶にくっつけてみましたが、この行をなくすとそもそもキャラが移動しませんでした。 とりあえず後日、お茶が取った後消えるようにして、それで不自然に見えるようなら減速について考えます。重ね重ねご丁寧なアドバイスありがとうございます。
Kageyama_23457

2020/01/11 12:29

すみません、上記を訂正します。この行がなくてもキャラは移動しました。ですが、依然kasokuスクリプトとIsTriggerでは加速しませんでした。
simapiko

2020/01/11 12:58

その行だけでは無いです。if(isKasoku==true){}とelse if(isKasoku==false){}とでも扱っています。なくても移動できているのはelse if...の条件を満たしているからかと思います。加速しない理由も同じです。
simapiko

2020/01/11 13:02

そもそも、移動を速度で操作してしまっているので、力を加えて加速というのは出来なくはないですが、複雑になるので自己解決の内容のように速度で纏めたほうが楽だと思います。
Kageyama_23457

2020/01/11 22:37

ありがとうございます。加速の他にもまだ色々とらせたい挙動があるので、「加速と力」のことを頭に入れておきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問