障害物に、プレイヤーを跳ね返してほしい。プレイヤーを妨害してほしい。
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度ランダムな方向に移動させたい」