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

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

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

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

Unity

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

Q&A

解決済

1回答

4860閲覧

###Unityで一度ぶつかったオブジェクトに対してはダメージ判定を行わないよにするにはどうすればいいのでしょうか?

donafudo

総合スコア46

C#

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

Unity

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

0グッド

1クリップ

投稿2017/02/22 14:20

お世話になります。

現在unity3Dで敵の当たり判定の処理を作っている最中なのですが
攻撃モーション中に武器にTriggerで当たり判定を行うのオブジェクトを生成して
そのオブジェクトの範囲に入ったらダメージ処理を行うようにしています。
その際に一度当たった後にアニメーションの動きなどでまた当たる、
同じ敵キャラクターの別のコライダーに当たる(頭や胴体など複数の判定を設定している)
などで2回以上の判定が発生してしまうことを直したいです。

敵の攻撃できるコライダーすべてにEnemy_DamageChildをつけて
DamageManagerで一括管理したいです

もっと良いやり方がありましたら教えて頂きたいです。よろしくお願いします。
###発生している問題・エラーメッセージ
2度当たり判定が発生する

###該当のソースコード
攻撃を当てられるコライダー

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class Enemy_DamageChild : MonoBehaviour { 6 7 public GameObject ParentObj;//ダメージマネージャーが入っているオブジェクト 8 9 Enemy_DamageManager Edm; 10 11 void Start () { 12 Edm = ParentObj.GetComponent<Enemy_DamageManager> (); 13 14 } 15 16 //攻撃がヒットした際に呼ばれる 17 public void AttackHitCol(GameObject HitAttack,int Damagenum){ 18 19 Edm.EnemyHPSystem (HitAttack,gameObject,Damagenum); 20 21 } 22 23 24}

当たり判定をまとめる

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using System.Collections.Generic; 5public class Enemy_DamageManager : MonoBehaviour { 6 public int HP 7 8 DamagePopManager Dpm; 9 10 void Start () { 11 //ダメージ表示用のキャンバス 12 Dpm = GameObject.Find ("DamagePopCanvas").GetComponent<DamagePopManager> (); 13 14 } 15 16 public void EnemyHPSystem(GameObject hitobj,GameObject HitCol,int Damagenum){ 17 18 //ココに判定を書きたい 19 Damage (HitCol,Damagenum); 20 21 } 22 //ダメージ処理 23 void Damage(GameObject hitCol,int Damagenum){ 24 //ダメージ表示 25 Dpm.DamagePopUp (Damagenum.ToString (), (Vector3)hitCol.transform.position); 26 27 } 28}

###試したこと
攻撃用のオブジェクトをリストで管理して
リストにすでに入っていたらダメージ処理を行わないようにしようとしたが
リストに入っていないことをどう判断すればいいかわからなかった

敵に当たった場合に攻撃用のオブジェクトを消すという手もありますが
それだと複数敵がいる場合に最初に当たった1体にしか判定が発生しないのが歯痒い

###補足情報(言語/FW/ツール等のバージョンなど)
より詳細な情報

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

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

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

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

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

guest

回答1

0

ベストアンサー

※僕はUnityでゲーム開発していないので、こういう処理が既に用意されてるかどうかは分かりません

リストの初期化は敵のObjectを破壊したときにできればいいってことでしょうかね。

ちょっと動くか確認していませんが、大体はこんな感じです。

C#

1private readonly List<int> hitIdList = new List<int>(); 2 3public void EnemyHPSystem(GameObject hitobj,GameObject HitCol,int Damagenum){ 4 // 1. オブジェクトのIDを取得します(GameObjectのリストにすると参照関係が怖いからね) 5 var instanceId = hitObj.GetInstanceId(); 6 // 2. オブジェクトのIDがリストに含まれていないか確認、含まれていれば処理終了 7 if (hitIdList.Contains(instanceId)) return; 8 // 3. オブジェクトのIDをリストに追加して処理に進む 9 hitIdList.Add(instanceId); 10 11 Damage (HitCol,Damagenum); 12 13}

これで2回同じ処理が行われないようにできます。
非同期で処理が行われていて多重に呼ばれてしまう場合はロックを実装しても同じような効果が得られます。

補足ですが、要素の有無を判定するだけの場合はHashSetクラスを使います。
HashSetクラスは、要素として値を持つかどうかを判定することだけに長けたクラスです。
Listとコード自体は一緒ですが、要素の検索を素早く行えます。

C#

1private readonly HashSet<int> hitIdSet = new HashSet<int>(); 2 3public void EnemyHPSystem(GameObject hitobj,GameObject HitCol,int Damagenum){ 4 var instanceId = hitObj.GetInstanceId(); 5 if (hitIdSet.Contains(instanceId)) return; 6 hitIdSet.Add(instanceId); 7 8 Damage (HitCol,Damagenum); 9 10}

#追記

こういう処理は沢山書くと思うので、専用のクラスを書いてラップしておくとすっきりします。
処理の修正が必要な場合でも一括で修正できるようになります。
※名前は適当!

C#

1public class ProcessGuard 2{ 3 private readonly HashSet<int> hitIdSet = new HashSet<int>(); 4 5 public bool PassOnce(GameObject obj) 6 { 7 var instanceId = obj.GetInstanceId(); 8 if (hitIdSet.Contains(instanceId)) return false; 9 hitIdSet.Add(instanceId); 10 return true; 11 } 12} 13 14//... 15 16private readonly ProcessGuard hitIdGuard = new ProcessGuard(); 17 18public void EnemyHPSystem(GameObject hitobj,GameObject HitCol,int Damagenum){ 19 if (!hitIdGuard.PassOnce(hitobj)) return; 20 21 Damage (HitCol,Damagenum); 22}

投稿2017/02/23 01:22

編集2017/02/23 02:23
haru666

総合スコア1591

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

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

donafudo

2017/02/23 12:41

今やってみたところ見事にできました! 完璧な回答ありがとうございます、これで少し前に進みそうです その他の実装方法も参考にさせていただきます。 本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問