🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C#

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

Unity

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

Q&A

解決済

1回答

1882閲覧

物体同士がくっついてしまう

actionstudio

総合スコア39

C#

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

Unity

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

0グッド

1クリップ

投稿2021/01/31 00:27

編集2021/01/31 10:34

前提・実現したいこと

Playerというボールを操作し、敵のボールを場外に落としていくゲームを作っています。

とても大きな敵(同じくぼーる)を出現させplayerにむかって移動します。その時、playerに触れたとき、大きく吹き飛ばします。なお、powerupをplayerが所有していれば吹き飛ばす力が小さくなります。

Big Enemy
Nomal Enemy
Player

がここでは登場しますが、

Massは
Big Enemy   1500
Nomal Enemy 5
Player 5

です。

それぞれColliderのMaterialは

Dynamic Friction 0.6
Static Friction 0.6
Bounciness 1
Friction Combine Average
Bounce Combine Multiply

となっています。

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

Big Enemyにplayerが接触したとき、吹き飛ばされるはずがくっついて離れなくなってしまうことがあります。

Nomal Enemyも同じように吹き飛ばされるスクリプトを書いてありますが、Nomal Enemyにはこのようなことがありません。
また特に、Big Enemyが登場するとき、上空から落下してくるのですが、落下しGroundに着地した瞬間にPlayerがBig Enemyに触れているとこの問題が起きやすいように感じます。さらに、BigEnemyが出現した瞬間に、それの下に潜り込むように接触しに行くと、それ以降PlayerがBigEnemyから離れなくなりました。

######予想
敵の下に潜り込んだ時に起こっているため、BigEnemyから下向きの力が加わって、弾き飛ばされるはずが、地面に押し付けられているようになっているのかもしれません。

該当のソースコード

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class BigEnemy : MonoBehaviour 6{ 7 private GameObject player; 8 private GameObject mainCamera; 9 10 private Rigidbody bigEnemyRb; 11 12 public float bigEnemySpeed = 10.0f; 13 public float blowOffStrengh = 15.0f; 14 15 private bool onGround = false; 16 17 private PlayerController playerControllerScript; 18 19 // Start is called before the first frame update 20 void Start() 21 { 22 player = GameObject.Find("Player"); 23 mainCamera = GameObject.Find("Main Camera"); 24 bigEnemyRb = GetComponent<Rigidbody>(); 25 playerControllerScript = GameObject.Find("Player").GetComponent<PlayerController>(); 26 27 } 28 29 // Update is called once per frame 30 void Update() 31 { 32 if (onGround == true) 33 { 34 moveToPlayer(); 35 } 36 } 37 38 private void moveToPlayer() 39 { 40 if (!playerControllerScript.gameOver) 41 { 42 if (playerControllerScript.readyToRanchSpecialWeapon) 43 { 44 bigEnemyRb.velocity = Vector3.zero; 45 } 46 else 47 { 48 Vector3 lookDirection = (player.transform.position - transform.position).normalized; 49 50 bigEnemyRb.AddForce(lookDirection * bigEnemySpeed); 51 } 52 } 53 } 54 private void OnCollisionEnter(Collision collision) 55 { 56 if (collision.gameObject.CompareTag("Nomal Enemy")) 57 { 58 Rigidbody nomalEnemyRigidbody = collision.gameObject.GetComponent<Rigidbody>(); 59 Vector3 awayFromBigEnemy = collision.gameObject.transform.position - transform.position; 60 61 nomalEnemyRigidbody.AddForce(awayFromBigEnemy * blowOffStrengh, ForceMode.Impulse); 62 } 63 64 if (collision.gameObject.CompareTag("Player")) 65 { 66 Rigidbody nomalEnemyRigidbody = collision.gameObject.GetComponent<Rigidbody>(); 67 Vector3 awayFromBigEnemy = collision.gameObject.transform.position - transform.position; 68 69 if (playerControllerScript.hasPowerup) 70 { 71 blowOffStrengh = 10f; 72 } 73 else 74 { 75 blowOffStrengh = 30f; 76 } 77 nomalEnemyRigidbody.AddForce(awayFromBigEnemy * blowOffStrengh, ForceMode.Impulse); 78 } 79 80 if (collision.gameObject.CompareTag("Ground")) 81 { 82 onGround = true; 83 StartCoroutine(ShakeCamera()); 84 } 85 } 86 IEnumerator ShakeCamera() 87 { 88 float shakeY = 10f; 89 float shakeInterval = 0.1f; 90 for (int i = 0; i < 15; i++) 91 { 92 yield return new WaitForSeconds(shakeInterval); 93 94 mainCamera.transform.Translate(0, shakeY, 0); 95 96 if (i % 2 == 0) 97 { 98 shakeY = shakeY * 0.5f * -1; 99 100 } 101 102 shakeInterval -= 0.01f; 103 } 104 105 mainCamera.transform.position = new Vector3(0, 10, -20); 106 } 107 108} 109

######補足 Playerのscript

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using UnityEngine.SceneManagement; 5using UnityEngine.UI; 6 7public class PlayerController : MonoBehaviour 8{ 9 private GameObject focalPoint; 10 public GameObject powerupIndicator; 11 public GameObject specialWeaponIndicator; 12 public GameObject nomalEnemyPrefab; 13 14 private Rigidbody playerRb; 15 private Rigidbody nomalEnemyPrefabRb; 16 17 public float powerUpStrengh = 15.0f; 18 public float defaltSpeed = 5.0f; 19 20 public bool hasPowerup = false; 21 public bool readyToRanchSpecialWeapon = false; 22 public bool hasSpecialWeapon = false; 23 public bool gameOver = false; 24 public static bool cameraForwardType = false; 25 public bool onGround; 26 public bool blownAwayByPlayerWithSpecialWeapon = false; 27 28 29 public ParticleSystem bigShockParticle; 30 public ParticleSystem smallShockParticle; 31 32 private AudioSource playerAudio; 33 public AudioClip highBounceSound; 34 public AudioClip coinSound; 35 public AudioClip lowBounceSound; 36 public AudioClip BigBounceSound; 37 public AudioClip getSpecialWeaponSound; 38 39 // Start is called before the first frame update 40 void Start() 41 { 42 Time.timeScale = 1.0f; 43 44 focalPoint = GameObject.Find("Focal Point"); 45 46 playerRb = GetComponent<Rigidbody>(); 47 nomalEnemyPrefabRb = nomalEnemyPrefab.GetComponent<Rigidbody>(); 48 49 playerAudio = GetComponent<AudioSource>(); 50 } 51 52 // Update is called once per frame 53 void Update() 54 { 55 Move(); 56 57 Jump(); 58 59 Destroy(); 60 } 61 62 private void Move() 63 { 64 if (!readyToRanchSpecialWeapon) 65 { 66 float speed; 67 if (cameraForwardType) 68 { 69 float forwardInput = Input.GetAxis("Vertical"); 70 71 if (onGround) 72 { 73 speed = defaltSpeed; 74 } 75 else 76 { 77 speed = defaltSpeed * 0.3f; 78 } 79 80 playerRb.AddForce(focalPoint.transform.forward * speed * forwardInput); 81 } 82 else 83 { 84 float verticalInput = Input.GetAxis("Vertical"); 85 float horizontalInput = Input.GetAxis("Horizontal"); 86 87 if (onGround) 88 { 89 speed = defaltSpeed; 90 } 91 else 92 { 93 speed = defaltSpeed * 0.3f; 94 } 95 playerRb.AddForce(focalPoint.transform.forward * speed * verticalInput); 96 playerRb.AddForce(focalPoint.transform.right * speed * horizontalInput); 97 } 98 } 99 } 100 101 102 103 104 private void OnTriggerEnter(Collider other) 105 { 106 if (other.CompareTag("Powerup") && !hasPowerup) 107 { 108 hasPowerup = true; 109 Destroy(other.gameObject); 110 StartCoroutine(PowerupCountdownRoutine()); 111 StartCoroutine(SetPowerupIndicatorPosition()); 112 113 playerAudio.PlayOneShot(coinSound, 0.4f); 114 } 115 116 if (other.CompareTag("Special Weapon") && !hasSpecialWeapon && onGround) 117 { 118 119 hasSpecialWeapon = true; 120 Destroy(other.gameObject); 121 122 StartCoroutine(SetSpecialWeaponIndicatorPosition()); 123 124 StartCoroutine(SetSpecialWeapon()); 125 126 playerAudio.PlayOneShot(getSpecialWeaponSound, 1f); 127 } 128 } 129 130 IEnumerator PowerupCountdownRoutine() 131 { 132 powerupIndicator.gameObject.SetActive(true); 133 yield return new WaitForSeconds(7); 134 hasPowerup = false; 135 powerupIndicator.gameObject.SetActive(false); 136 } 137 138 IEnumerator SetPowerupIndicatorPosition() 139 { 140 while (hasPowerup) 141 { 142 powerupIndicator.transform.position = transform.position + new Vector3(0, -0.5f, 0); 143 144 yield return null; 145 } 146 } 147 148 149 150 private void OnCollisionEnter(Collision collision) 151 { 152 if ((collision.gameObject.CompareTag("Nomal Enemy") || collision.gameObject.CompareTag("Mitosis Enemy")) && hasPowerup) 153 { 154 Rigidbody nomalEnemyRigidbody = collision.gameObject.GetComponent<Rigidbody>(); 155 Vector3 awayFromPlayer = collision.gameObject.transform.position - transform.position; 156 157 nomalEnemyRigidbody.AddForce(awayFromPlayer * powerUpStrengh, ForceMode.Impulse); 158 smallShockParticle.Play(); 159 //Debug.Log("Player collided with: " + collision.gameObject.name + " with powerup set to " + hasPowerup); 160 161 playerAudio.PlayOneShot(highBounceSound, 4f); 162 } 163 else if ((collision.gameObject.CompareTag("Nomal Enemy") || collision.gameObject.CompareTag("Mitosis Enemy")) && !hasPowerup) 164 { 165 playerAudio.PlayOneShot(lowBounceSound, 0.6f); 166 } 167 168 169 } 170 171}

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

unity 2020.1.2f1
windows10

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

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

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

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

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

Bongo

2021/01/31 07:25

Nomal Enemyに対してもPlayerに対しても吹き飛ばし処理はほぼ同じようですが、くっついてしまう現象はNomal Enemyには起こらず、Playerだけに起こるのでしょうか?
actionstudio

2021/01/31 07:50

修正しました。わかりづらくてすみませんでした。
Bongo

2021/01/31 08:22

いえいえ、追記ありがとうございます。Playerに対してしか現象が起こらないとなると、プレイヤーのスクリプトが何らかの干渉をしている可能性はないでしょうかね?差し支えなければPlayerのスクリプトもご提示いただけませんでしょうか。 また、Big Enemy登場時の着地タイミングで発生しやすそうだとのことですが、他にも発生条件に影響しそうな要素はないでしょうか?たとえば、Big Enemyに接触する瞬間にプレイヤーへの入力操作がある場合と、何も入力せずなすがままにした場合とで現象の発生しやすさが変わるでしょうか。
actionstudio

2021/01/31 10:35

かなり省略した部分がありますが、問題になりそうな部分を書き加えました。 追記したように、bigenemyの下に潜り込んだ時に起こってしまっています。
actionstudio

2021/01/31 13:18

この質問は今回の問題と直接関係はないのですが、 コードを書く場合、UnityからC#スクリプトをクリエイトしてダブルクリックで開いて記述し始めますよね。visualStudioをunity上ではなく直接開いて、記述するにはどうすればいいのでしょうか。新規作成で記述をしたいです。 調べたのですが解決できませんでした。 もしよろしければ教えてください。
guest

回答1

0

ベストアンサー

はたしてご質問者さんの状況を再現できているかどうか不確かなものの、模擬シーンを作ってみて挙動を確認してみました。
Big Enemyが地上にある状態でPlayerがBig Enemyに接触したときと、Big Enemyが落下してきてPlayerを押しつぶすような位置関係にあるときでは、接触時の速度のY成分にかなりの差があるように思われました。Big Enemyに押しつぶされる状況ではPlayerが地面に向かって弾き飛ばされることになりますので、地面との摩擦が強烈に働いてPlayerを減速させているんじゃないかと思われました。
そこで、AddForceで吹き飛ばす代わりにVelocityの書き換えで吹っ飛ばすようにしてはいかがかと思いました。これなら速度のY成分に関係なく直接的に速度が設定されますので、摩擦の影響を無視して一定の吹っ飛びになるんじゃないでしょうか。
BigEnemyのスクリプトの吹っ飛ばす部分を、下記のように変更してみてはいかがでしょう。

C#

1 private void OnCollisionEnter(Collision collision) 2 { 3 if (collision.gameObject.CompareTag("Nomal Enemy")) 4 { 5 Rigidbody nomalEnemyRigidbody = collision.gameObject.GetComponent<Rigidbody>(); 6 Vector3 awayFromBigEnemy = collision.gameObject.transform.position - transform.position; 7 awayFromBigEnemy.y = 0.0f; 8 awayFromBigEnemy.Normalize(); 9 10 nomalEnemyRigidbody.velocity = awayFromBigEnemy * blowOffStrengh * nomalEnemyRigidbody.mass; 11 } 12 13 if (collision.gameObject.CompareTag("Player")) 14 { 15 Rigidbody nomalEnemyRigidbody = collision.gameObject.GetComponent<Rigidbody>(); 16 Vector3 awayFromBigEnemy = collision.gameObject.transform.position - transform.position; 17 awayFromBigEnemy.y = 0.0f; 18 awayFromBigEnemy.Normalize(); 19 20 if (playerControllerScript.hasPowerup) 21 { 22 blowOffStrengh = 10f; 23 } 24 else 25 { 26 blowOffStrengh = 30f; 27 } 28 nomalEnemyRigidbody.velocity = awayFromBigEnemy * blowOffStrengh * nomalEnemyRigidbody.mass; 29 } 30 31 if (collision.gameObject.CompareTag("Ground")) 32 { 33 onGround = true; 34 StartCoroutine(ShakeCamera()); 35 } 36 }

なお、これによってPlayerが地面に接している場合の重力による地面への押しつけに基づく摩擦による減速も無効化されるでしょうから、blowOffStrenghをもっと小さくしてやらないと吹っ飛びすぎるかもしれません。

Visual Studio上で新規スクリプトを作成する場合は、ソリューションエクスプローラーのスクリプトを置きたいフォルダ上で「追加」を行えばいいんじゃないでしょうか。Unityに戻るとファイルがインポートされ、スクリプトとして使えるようになるかと思います。

図

投稿2021/01/31 22:40

Bongo

総合スコア10811

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

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

actionstudio

2021/01/31 23:53 編集

とても分かりやすかったです!ありがとうございます。 今、試しているのですが少し質問があります。 ``` awayFromBigEnemy.Normalize(); ``` この部分についてなのですが、これはなぜ必要なのでしょうか。接触したときに力が加わるため、接触したときの距離はそれほど考慮する必要がないように感じたのですが。 追記 ``` awayFromBigEnemy.y = 0.0f; ``` この部分から、下に向かって力が加わらなければ摩擦が大きくなってくっついてるように見える問題が発生しなくなるのではないかと思い、 ``` Rigidbody nomalEnemyRigidbody = collision.gameObject.GetComponent<Rigidbody>(); Vector3 awayFromBigEnemy = collision.gameObject.transform.position - transform.position; awayFromBigEnemy.y = 0f; nomalEnemyRigidbody.AddForce(awayFromBigEnemy * blowOffStrengh, ForceMode.Impulse); ``` としたところ、うまくできました! velocityを使うと物理的に変な挙動になってしまうことがあると調べて分かったので、上に示したやり方にしようと思います。 ありがとうございました。
Bongo

2021/02/01 00:08

うまくいきましたようで安心しました。投稿しましたコードのNormalizeですが、あれはPlayerとBig Enemyの接触位置がどこであろうと一定の吹っ飛びにしようと思ってのことでした。Big Enemyはその名の通りPlayerよりもけっこう大きいボールなんだろうと考えまして、そうなるとPlayerがBig Enemyのほぼ真下で押しつぶされた場合と、Big Enemyの周辺部でかすめるように弾かれた場合とで吹っ飛び量に差が出てしまうのではないか...と思って付け加えたものです。ですがあれは今回の問題の主題ではありませんので、Normalizeなしで問題ないようでしたらそれでかまわないと思います。
actionstudio

2021/02/01 11:10

わかりました!そういうことだったのですね。たくさんのことを教えていただきありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問