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

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

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

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

スクロール

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

Unity

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

Q&A

1回答

2772閲覧

Unityタテスクロール障害物競争 障害物に、プレイヤーを跳ね返してほしい

Kageyama_23457

総合スコア21

C#

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

スクロール

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

Unity

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

0グッド

1クリップ

投稿2020/01/20 00:05

編集2022/01/12 10:55

障害物に、プレイヤーを跳ね返してほしい。プレイヤーを妨害してほしい。

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

この度は障害物(移動する)について質問致します。

###実現したいこと

現実の物理法則とは違いますが、このようにキャラの走行を妨害してほしいです。
実際人間がプレイするにあたって、「車に当たるとタイムロスなので避けるようにする」となるようにしたいです。
イメージ説明

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

車のプレハブにつけるスクリプトを、3箇所のサイト様のコードを試しましたが、それぞれ問題が生じます。

※1月22日修正:ご教授頂き、エラーが出ていた箇所などを訂正したものに変えました。
こちら様
問題:キャラにぶつかっても車は止まりませんが、キャラは弾き飛ばされません。

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class kuruma03 : MonoBehaviour 6{ 7 public float Speed;//移動速度 8 9 public float radius = 10.0f; 10 public float power = 100.0f; 11 12 private bool nonVisibleAct;//映ってなくても動いてる 13 14 Rigidbody2D rb = null; 15 private SpriteRenderer sr = null; 16 17 void Start() 18 { 19 rb = GetComponent<Rigidbody2D>(); 20 sr = GetComponent<SpriteRenderer>();//自身が画面に映っているか判断 21 } 22 void LateUpdate()//普通のUpdateでいいのかLateあるいはFixedの方がいいのかよくわかってません。 23 { 24 //float x = Random.Range(-1f, 1f); 25 rb.velocity = new Vector2(Speed, 0);/*車がキャラにぶつかっても止まらないようにStart内からUpdate内に書き換えましたが、 26 上のfloat xをアクティブにすると車が左右にブレ続け移動しないという挙動不審になります。*/ 27 } 28 void OnCollisionEnter2D(Collision2D coll)//@ 29 { 30 var colliders = Physics2D.CircleCastAll(transform.position, 1, Vector2.zero); 31 /*コピペしたところ";が必要です"とメッセージが出たのでつけました。*/ 32 foreach (var col in colliders) 33 { 34 if (col.rigidbody != null)//★ご教授頂き、"GetComponent<Rigidbody2D>()"を"col.rigidbody"に書き換えました。 35 { 36 var diff = col.transform.position - transform.position; 37 col.rigidbody.AddForce(diff * 5f, ForceMode2D.Impulse);//★同上、書き換えました。 38 } 39 } 40 } 41}//出処:テラシュール様 結果:キャラは車に押されますが、弾き飛ばされません。

こちら様
問題:こちらは元来Rigidbody用のものをご教授頂きRigodbody2Dに書き換えました。
ですが①同様、キャラにぶつかっても車は止まりませんが、キャラは弾き飛ばされません。

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class kuruma04 : MonoBehaviour 6{ 7 public float Speed;//移動速度 8 9 public float radius = 10.0f; 10 public float power = 100.0f; 11 12 private bool nonVisibleAct;//映ってなくても動いてる 13 Rigidbody2D rb = null; 14 private SpriteRenderer sr = null; 15 16 void Start() 17 { 18 rb = GetComponent<Rigidbody2D>();//車プレハブのインスタンスを取得 19 sr = GetComponent<SpriteRenderer>();//自身が画面に映っているか判断 20 } 21 22 void LateUpdate()//普通のUpdateでいいのかLateあるいはFixedの方がいいのかよくわかってません。 23 { 24 //float x = Random.Range(-1f, 1f); 25 rb.velocity = new Vector2(Speed, 0);/*車がキャラにぶつかっても止まらないようにStart内からUpdate内に書き換えましたが、 26 上のfloat xをアクティブにすると車が左右にブレ続け移動しないという挙動不審になります。*/ 27 } 28 29 void OnCollision2D(Collision _other)/*ここの"OnCollisionEnter2D"が、Unity側で"This message parameter has to be of type:Collision2D"と出ます。 30 エラーが出たままでもシーン自体は動くのですが、書き換えました。*/ 31 { 32 if (_other.gameObject.tag == "chara") 33 { 34 // 力を発生させる場所 35 Vector2 explosionPos = gameObject.transform.position;//元はVector3ですが書き換えました。 36 // 中心点から設定した半径の中にあるcolliderの配列を取得する。 37 Collider[] colliders = Physics.OverlapSphere(explosionPos, radius); 38 foreach (Collider hit in colliders) 39 { 40 // 力を及ぼしたいオブジェクトにRigidbodyが付いていることが必要(ポイント) 41 Rigidbody2D hitrb = hit.GetComponent<Rigidbody2D>();/*元はRigidbodyですが書き換えました。 42 こちらでは「衝突したオブジェクトのインスタンス(rigidbody2D)を取得」命令の必要がある。 43 クラスで宣言している車プレハブの変数rbと競合していたのでhitrbとしました。*/ 44 45 if (hitrb != null) 46 { 47 _other.rigidbody.AddExplosionForce(power, explosionPos, 5.0f);/*"rb"だと赤線が引かれ、 48 「'Collision' に 'rb' の定義が含まれておらず、型 'Collision' の最初の引数を受け付けるアクセス可能な拡張メソッド 'rb' が見つかりませんでした。 49 using ディレクティブまたはアセンブリ参照が不足していないことを確認してください。」と出るので、 50 "rigidbody"に書き換えたところエラーは消えました。rigidbody2Dだと書き換え前と同じエラーが出ます。 51 ただしやはり、キャラは弾き飛ばされません。*/ 52 // 取得したRigidbodyに力を加える 53 // 3つの引数(加える力の強さ、力の中心点、力を及ぼす半径) 54 } 55 } 56 } 57 } 58}//出処 質問ページの②のサイト様 結果:キャラは車に押されますが、弾き飛ばされません。 59 /*自分用メモ:「次のメソッドまたはプロパティ間で呼び出しが不適切です」→当該スクリプト内、あるいは所属するソリューション内で、 60 引数などがダブっててVS側が「どっちを呼び出せばいいのかわからない」となっている。*/

こちら様(英語サイト)
問題:上記2つ同様、キャラにぶつかっても車は止まりませんが、キャラは弾き飛ばされません。

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class kuruma06 : MonoBehaviour 6{ 7 Rigidbody2D rb; 8 public float Speed; 9 private SpriteRenderer sr = null; 10 11 void Start() 12 { 13 rb = GetComponent<Rigidbody2D>(); 14 sr = GetComponent<SpriteRenderer>();//自身が画面に映っているか判断 15 } 16 17 void LateUpdate()//普通のUpdateでいいのかLateあるいはFixedの方がいいのかよくわかってません。 18 { 19 //float x = Random.Range(-1f, 1f); 20 rb.velocity = new Vector2(Speed, 0);/*車がキャラにぶつかっても止まらないようにStart内からUpdate内に書き換えましたが、 21 上のfloat xをアクティブにすると車が左右にブレ続け移動しないという挙動不審になります。*/ 22 } 23 24 public float explosionStrength = 500; 25 void OnCollisionEnter2D(Collision2D _other)//@ 26 { 27   _other.rigidbody.AddExplosionForce(explosionStrength, this.transform.position,5); 28 } 29 //自分用メモ:「現在のコンテキストに〜という名前は存在しません」→〜の記述位置から見て遠い、あるいはそもそもスクリプト内で定義されておらず、〜を参照できない。 30} 31 32public static class Rigidbody2DExt 33{ 34 public static void AddExplosionForce(this Rigidbody2D rb, float explosionForce, Vector2 explosionPosition, float explosionRadius, float upwardsModifier = 0.0F, ForceMode2D mode = ForceMode2D.Force) 35 { 36 var explosionDir = rb.position - explosionPosition; 37 var explosionDistance = explosionDir.magnitude; 38 39 // Normalize without computing magnitude again 40 if (upwardsModifier == 0) 41 explosionDir /= explosionDistance; 42 else 43 { 44 // From Rigidbody.AddExplosionForce doc: 45 // If you pass a non-zero value for the upwardsModifier parameter, the direction 46 // will be modified by subtracting that value from the Y component of the centre point. 47 explosionDir.y += upwardsModifier; 48 explosionDir.Normalize(); 49 } 50 rb.AddForce(Mathf.Lerp(0, explosionForce, (1 - explosionDistance)) * explosionDir, mode); 51 } 52} 53//出処:英語サイト 結果:キャラは車に押されますが、弾き飛ばされません。

###キャラの移動について
現在、プレイヤーキャラ、CPUともにVelocityで動かしておりますが、
プレイヤーキャラをAddForceで動かすスクリプトも持っております。
もしこの度の問題が、移動をAddForceにしないと解決しないということでしたらそう致します。
ご教授頂きたく存じます。

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

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

■ここまで出来ていること
・プレイヤーキャラクターのアニメ遷移
(待機時:歩いている→下キー入力:走る(手足の動きが早くなる))
・プレイヤーキャラクターの下と左右の移動。上に行く必要はないので、上キーを入力しても動きません。
・カメラのプレイヤー追従(y軸のみ)
・CPUキャラの自走(y軸下に向けて進むだけですが)
・オブジェクトのランダム座標生成、及びランダムな方向への移動
・加速アイテム実装

ここまで同じゲームで質問させて頂き、解決に至るご教授を頂いておりますので、
そちらのページも貼っておきます。

同質問者のページ 「加速アイテムに時間制限をつけたい」
同質問者のページ 「ランダム生成したオブジェクト(アイテム、障害物)を、360度ランダムな方向に移動させたい」

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

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

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

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

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

Y0241-N

2020/01/20 05:19

既に試していたら恐縮ですが、①のdiff * 0.06fの部分の0.06fを5fぐらいの数値に変更した場合どうなりますか? それと②のAddExplosionForceについてですが、3Dと2Dでは使用されている物理演算の計算方法(?)が異なるため、2DにはAddExplosionForceが存在しません。なのでエラーが出ます、これを解決するには自分でAddExplosionForceが行っている物理計算式を記述し、引用する方法があります、
Kageyama_23457

2020/01/20 07:12

Y0241-N様 前回はありがとうございました! ①の数値ですが、5でやってみましたが0.06と変化ありませんでした。 また、念のため車のRIgidbody2DのMassを1000に、キャラのMassを60にして(体重をイメージ)、 ○:キャラ ■:車 ○←ーー■ このようにぶつけてみましたがふっとびませんでした。 ②についてはお恥ずかしいのですが現時点では自分で書けないうえ、「AddExplosionForce 計算式/物理計算式/自力」などと検索しましたがいまひとつ参考になりそうなところが見つけられなかったので、申し訳ないのですが検索のアドバイスなど頂けると幸いです。
Y0241-N

2020/01/20 07:54

なるほど、変化なしですか...。 少し調べてみたのですが、どうもForceMode2D.Impulseを使用した際に動かないという事例は過去にもあるようなんですよね、解決方法までは分かりませんでしたが...。 ②件ですが、英文の記事になりますがここの回答に書かれている内容がAddExplosionForceに該当すると思われます。私も詳しいことは分かりませんが...。 https://stackoverflow.com/questions/34250868/unity-addexplosionforce-to-2d
Kageyama_23457

2020/01/20 08:38

②のサイト、試してみたので質問欄に追加しました。しかし質問欄の通りこちらも実装できません…
Y0241-N

2020/01/20 08:50

あーpublic class kuruma05 : MonoBehaviour{}とは別にpublic static class Rigidbody2DExt {}を記述してその中にpublic static void AddExplosionForce入れてみてください。 で呼び出しの方は英文記事の下の方のコードのように public class kuruma05 : MonoBehaviour{}の中にvoid OnCollisionEnter2D( Collision2D _other) を書いて_other.rigidbody.AddExplosionForce(explosionStrength, this.transform.position,5);のように使います
Y0241-N

2020/01/20 08:52 編集

public class kuruma05 : MonoBehaviour {   void OnCollisionEnter2D( Collision2D _other)  {    other.rigidbody.AddExplosionForce(explosionStrength, this.transform.position,5);  } } public static class Rigidbody2DExt {  public static void AddExplosionForce...省略 } こういう感じです
simapiko

2020/01/20 09:51 編集

①について、おそらく車にアタッチされているのかと思いますが、書き換え後の内容だと車自身のRigidbodyにAddforceしています。OnCollisionEnter2D()の中にある「GetComponent<Rigidbody2D>()」の部分を「col.rigidbody」に書き換えてみて下さい。また、跳ね返りが鈍い場合は0.06の値を大きくして調節して下さい。
Kageyama_23457

2020/01/20 23:44

>>simapiko様 前回はありがとうございました! 以下のようにやってみましたが… void OnCollisionEnter2D(Collision2D coll) { var colliders = Physics2D.CircleCastAll(transform.position, 1, Vector2.zero); foreach (var col in colliders) { if (col.rigidbody != null)//★ { var diff = col.transform.position - transform.position; col.rigidbody.AddForce(diff * 5f, ForceMode2D.Impulse);//★ } 訂正箇所は★の2箇所であっていますでしょうか? VSではエラーは出ませんが、挙動は変わりませんでした。車が止まってしまいます。そして"rigidbody2D"にすると、VSで赤線が引かれ、 「'RaycastHit2D' に 'rigidbody2D' の定義が含まれておらず、型 'RaycastHit2D' の最初の引数を受け付けるアクセス可能な拡張メソッド 'rigidbody2D' が見つかりませんでした。using ディレクティブまたはアセンブリ参照が不足していないことを確認してください。」 とメッセージが出ます。
Kageyama_23457

2020/01/21 00:21

>>Y241-N様 ③について、質問欄の通り書き換えてみましたが、質問欄の通り問題が2つ出ます。 そして、こちらの追記修正欄にて頂いたお手本も以下のように試しましたが、 public class kuruma06 : MonoBehaviour { void OnCollisionEnter2D(Collision2D _other) {    other.rigidbody.AddExplosionForce(explosionStrength, this.transform.position,5); } } "other","explosionStrength"に赤線が引かれ、どちらも 「現在のコンテキストに〜という名前は存在しません。」と出ます。
Y0241-N

2020/01/21 00:35 編集

エラーメッセージが出る理由はエラーメッセージの通りだからです、つまり接触した相手のRigidbody2Dを取得していないので参照できないと言われています。 なので②のforeach (Collider hit in colliders)、Rigidbody2D rb = hit.GetComponent<Rigidbody2D>();、if (rb != null)を追加して_other.rb.AddExplosionForceとしてください。 エラーメッセージが出た際はとりあえず丸々コピーして検索すると大体の場合解決方法が出ますよ。 お言葉ですが、エラーメッセージの意味を理解しようとする前に質問されている気がします。 意味のないエラーメッセージはないので、どういう意味かを少し考えてみてください。 "other","explosionStrength"に関してはkageyama_23457様の力量なら分からないエラーだとは思えません。
simapiko

2020/01/21 00:56 編集

その二箇所で合っています。col.rigidbodyのrigidbodyの型はRigidbody2Dになっているので変えなくても大丈夫です。 参考https://docs.unity3d.com/ja/2017.4/ScriptReference/Collision2D-rigidbody.html 止まってしまうのは、プレイヤー接触時に車が減速しているからかと思います。Start()時のみ速度指定しているので、車の速度が変更される度に再び指定してあげればいいと思います。 そういえば、前回プレイヤー自身も速度で動かしていた気がするので、外部から力を加えても速度を上書きされて吹き飛ばないような気がします。接触した反動がある間は速度を変更しないようにする必要があるかもしれません。
Kageyama_23457

2020/01/22 12:32

>>Y0241-N様 たいへんご丁寧なご指導、本当にありがとうございます。おかげさまで、現在載せている3つのスクリプトについてエラー等について調べ、現在手元ではVS、Unityともにエラーが出ない状態まで持ってこられました。ですが、やはり弾き飛ばされるという現象は起きません。 そして、大変申し訳ないのですが、車については、キャラにぶつかっても止まらないというところまで持ってこられた結果、弾き飛ばされるのではなく、ダウン処理(ダウンアニメ付きで、3秒ほどその場から動けない)の方がいいのでは? という考えに至りました。(加速アイテムのコルーチンを改造し、手元にて実装できています) ですが、弾き飛ばし処理については、キャラ同士がぶつかった場合に於いても使いたいと思っていたので、車ではなくなりますが、引き続き実現を目指して調べる所存です。(ゾウ>カバ>シマウマ>ネズミのような概念で、キャラの体重で4グループほどに分けてタグをつけ、「相手を弾き飛ばす」というより、「自分より重いタグのキャラにぶつかったら弾かれる」という処理ができないものかと考えております) せっかくご丁寧にご教授を頂いているのに考えを変えて申し訳ございません。どうかご容赦頂きたく存じます。 とりあえず、質問欄のスクリプト3つはエラーが出ない状態のものに変えておきます。
Kageyama_23457

2020/01/22 12:38

>>simapiko様 ご教授ありがとうございました。おかげさまで、車がキャラにぶつかっても止まらないようにできました。ですが、依然弾き飛ばされるという挙動は起きません。 そして、以下、上記Y0241-N様への欄でも同様のことを申し上げたのですが、 車が止まらなくなった結果、車に弾き飛ばされるのではなく、ダウン処理の方がいいのでは? という考えに至りました。(ダウンアニメ付きで、3秒ほどその場から動けない。加速アイテムのコルーチンから改造して、手元にて実装できています) ですが、弾き飛ばし処理については元々、キャラ同士がぶつかった場合に於いても使いたいと思っていたので、車ではなくなるのですが、引き続き実現を目指して調べる所存です。(ゾウ>カバ>シマウマ>ネズミのような概念で、キャラの体重で4グループほどに分けてタグをつけ、「相手を弾き飛ばす」というより、「自分より重いタグのキャラにぶつかったら弾かれる」という処理ができないものかと考えております) せっかくご教授を頂いている中、考えを変えて申し訳ございません。どうかご容赦頂きたく存じます。
simapiko

2020/01/23 01:16 編集

弾き飛ばされない原因は上のコメントでも申した通り、Player側に問題があります。(現にスクリプトを付けていないオブジェクトに対しては弾き飛ばせる事が出来ているので) 前回の加速と同様に弾く力を加えてもPlayer側で速度が上書きされているので、何か別の動作をさせる場合は速度の上書きをスルーする必要があります。 ダウンに関しては、自分がしっくりくる方でいいのではとしか言えないです。おそらく、速度を0にして実装しているのだと勝手に推測しますが、どのみちキャラ同士を弾く処理でUnityの物理演算で処理する場合、速度の上書きはスルーする必要があるので、ダウンでも弾くのでもあまり変わりはないのではと考えてます。 (弾くというのを物理公式に当てはめて自力で計算する場合は速度でも可能なので、その場合上書きをスルーする必要は無くなりますが。) 実装方法についてはPlayerごとに相手のタグを判断して自身を弾いたり、どのオブジェクトが接触したかを判定用にオブジェクトに渡して、軽い方を弾く等方法は沢山あると思うのでそれについてはまた別のスレッドを立てる方がいいかもしれません。
guest

回答1

0

そのキャラにPhysics Materialをつけるのはどうでしょうか?
そのキャラにRigid bodyをアタッチし、左上の部分から、
Asetts→Creata→Physics Material
をして、そのキャラのコライダーMaterialというところにアタッチしてあげればいいと思います。

投稿2020/04/10 05:30

leeee1019

総合スコア9

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問