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

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

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

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

Unity

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

Q&A

解決済

2回答

1490閲覧

UnityでアクションRPGゲームを作成しているのですが攻撃の実装方法について

kknk

総合スコア7

C#

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

Unity

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

0グッド

4クリップ

投稿2018/06/04 23:57

編集2018/06/06 09:44

現在UnityでアクションRPGゲームを作成しているのですが攻撃の実装方法に悩んでいます。

プレイヤーの持っている武器にColliderを設定してOntriggerEnter2Dで接触判定を取り、IDamageableインターフェースを継承したオブジェクトならばDamageメソッドを呼びだしてそれ­ぞれのダメージ処理を行うというようにしているのですが、攻撃には属性があり、こんぼうなら打撃、剣なら斬撃、炎属性の剣なら炎と斬撃を持っていたとして、攻撃を受けたオブジェクトは受けた攻撃の属性によってそれぞれ違う処理を行うようにしたいと思いこのように作ってみたのですが

攻撃の属性

C#

1public enum Type{ 打撃, 斬撃,,} 2

インターフェース

C#

1public interface IDamageable 2{ 3 void Damage(float power, List<Type> types); 4}

装備している武器

C#

1public class Weapon : MonoBehaviour 2{ 3 public float weaponpower; 4 5 //攻撃中だけ武器のColliderが有効になる 6 void OnTriggerEnter2D(Collider2D Hitcollider) 7 { 8 //当たったオブジェクトがIDamageableを継承したオブジェクトなら 9 if (Hitcollider.GetComponent<IDamageable>() != null) 10 { 11 //炎属性の剣の場合 12 List<Type> types = new List<Type> { Type.斬撃, Type., }; 13 14 Hitcollider.GetComponent<IDamageable>().Damage(weaponpower, types); 15 } 16 } 17} 18

ダメージを受けるオブジェクト

C#

1//敵 2public class Enemy : MonoBehaviour, IDamageable 3{ 4 public void Damage(float power, List<Type> types) 5 { 6 for (int i = 0; i < types.Count; i++) 7 { 8 switch (types[i]) 9 { 10 case Type.: 11 //炎のダメージをうけたら燃える 12 break; 13 case Type.: 14 //毒のダメージをうけたら毒状態になる 15 break; 16 case Type.斬撃: 17 case Type.打撃: 18 //斬撃、打撃はHPを減らす 19 //HP-=power; 20 break; 21 } 22 } 23 } 24}

C#

1//木箱 2public class Kibako : MonoBehaviour, IDamageable 3{ 4 public void Damage(float power, List<Type> types) 5 { 6 for (int i = 0; i < types.Count; i++) 7 { 8 switch (types[i]) 9 { 10 case Type.: 11 //炎のダメージをうけたら燃える 12 break; 13 case Type.斬撃: 14 case Type.打撃: 15 //斬撃、打撃ならバラバラになる 16 break; 17 } 18 } 19 } 20}

この処理の仕方は正しいでしょうか?
独学で勉強して作っているので何が正しくて間違いなのかわかりません。この処理の仕方が正しいのかどうか考えれば考えるほどわからなくなってしまいます。

追記しました

遅くなりすみません。自分のやりたかった通りに動きはしたのですがしばらくしてからもう一度自分の書いたコードを見てみるともっと他に良いやり方があるんじゃないかと考えてしまい何度もコードを書き直しては考え書き直しては考えを繰り返して最終的に結局最初と同じようなコードになったりして全く先に進めません。
今回自分が書いた、相手にダメージを与えて攻撃対象(モンスターや木箱)によって処理を変えて、攻撃に使用した武器に設定されている属性によっても処理を変えたい場合のコードの書き方が今回のやり方で問題はないのかというところで悩んでおり、もっと良いやり方があるとかそのやり方はまずいなどの回答をもらえるとありがたいです。

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

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

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

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

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

negitama

2018/06/05 05:53

まず、質問者さんの挙げているコードは動くのかどうか、もし「期待どおり動かない」ということであれば「期待する結果との違い」は具体的に何なのか、そのあたりを示してほしいです。
guest

回答2

0

sakura_hana さんの回答コードでもそうされていますが、Weapon クラスの types についてはインスペクターから指定するようにしておくと、複数の武器種で使いまわせるので便利かと思います。

Enemy や Kibako についても HP や弱点の属性などをインスペクターから指定するようにしておくといいかもしれませんね。


以下は蛇足かもしれませんが、いったん書いたものなので残しておきます。

「このコードが動くか?」というのは試してみればわかることで、「エラーになるがどこが原因か?」というのも、答えるのは比較的簡単です。
(質問者さんのコードを試してみましたが、特にエラーなく動作しますね)

しかし今回のような「このコードは最適か?」という意図の質問には、かなり答えるのが難しいです。実装方法には数多くのパターンがあり、目的によって解が異なるためです。

  • A) 単純に読みにくいので、読みやすく整理したい
  • B) 現状では処理負荷が高すぎてガクつくので改善したい
  • C) EnemyとKibako以外にも多くの種類のDamageableオブジェクトを用意するのに、クラスごとに同じコードを繰り返し書いているのでまとめたい
  • D) Enemyの処理は簡易なもので仮置きしているが、将来的にはもっと複雑な別の処理に置き換えたい

など

上記A,Bに関しては現状それほど問題になっていないのではないかと想像します。
上記のCの改善のためには sakura_hana さんの回答のように、EnemyとKibakoに共通の親クラスを用意して共通処理を親クラスに移すのが一案です。
いずれにしても、開発を進めながら必要が生じたときに、必要な箇所に対して改良を行う、くらいの考え方がいいんじゃないかと思います。

投稿2018/06/06 12:58

編集2018/06/06 12:58
negitama

総合スコア943

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

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

kknk

2018/06/06 22:24

回答ありがとうございます。 そこまで考えすぎず現状での自分の力で考えつく最適だと思うコードを書いて作っていき問題(処理の負荷が高いなど)が生じた場合にコードを見直してみようと思います。これで先に進めそうです!ありがとうございます。またよろしくお願いします。
guest

0

ベストアンサー

※個人的感想が強いので参考までに。もっと良案ありそうだなーとは思います。

「正しいコード」というのは、とどのつまり「動くか動かないか」「高速・低負荷で動作するかどうか」「メンテナンス性が高いかどうか」等が考えられます。
今回のコードは恐らく動くと思いますし速度も極端に遅くなるとは思わないので、「一見綺麗に見えないが、これはこれで最適解かも」と思います。

例えばC#らしくポリモーフィズムに則るなら以下の通り。(正しく則れているかは怪しい)

C#

1//攻撃の属性クラス(変数は適当) 2public class AttackType { 3 public string name; 4 public sprite icon; 5} 6 7//攻撃属性クラスを継承した各属性作る 8public class AttackSlash : AttackType { //斬撃 9} 10public class AttackFire : AttackType { //炎 11} 12 13//ダメージを受けるオブジェクトの基底クラス 14//インターフェースではなく抽象クラスにする(MonoBehaviour入れるならここ) 15public abstract Damageable : MonoBehaviour 16{ 17 public void Damage (float power, AttackSlash type) { 18 //斬撃ダメージ時のデフォ処理 19 } 20 public void Damage (float power, AttackFire type) { 21 //炎ダメージ時のデフォ処理 22 } 23 public void Damage (float power, AttackType type) { 24 //それ以外のダメージ時のデフォ処理 25 } 26} 27 28//武器クラス 29public class Weapon : MonoBehaviour { 30 public float weaponpower; 31 public AttackType[] types; //インスペクタから入れるなり装備時に入れるなりしておく 32 33 //攻撃中だけ武器のColliderが有効になる 34 void OnTriggerEnter2D(Collider2D Hitcollider) 35 { 36 //当たったオブジェクトがIDamageableを継承したオブジェクトなら 37 if (Hitcollider.GetComponent<Damageable>() != null) 38 { 39 foreach (var item in types) { 40 Hitcollider.GetComponent<Damageable>().Damage(weaponpower, item); 41 } 42 } 43 } 44} 45 46//敵クラス 47public class Enemy : Damageable { 48 public void Damage (float power, AttackSlash type) { 49 //斬撃ダメージ時の処理(デフォ処理と違う処理をしたい場合) 50 } 51 52 //デフォ通りの処理をするならそのメソッドの実装の必要は無い 53} 54 55//木箱クラス 56public class Kibako : Damageable { 57 public void Damage (float power, AttackSlash type) { 58 //斬撃ダメージ時の処理(デフォ処理と違う処理をしたい場合) 59 } 60 61 //デフォ通りの処理をするならそのメソッドの実装の必要は無い 62}

この方法の利点は属性が増えた時にDamageableクラスを拡張するだけでいいこと……なのですが、結局個別処理しようと思ったら継承先のメソッドも追記することになるので、今のコードとあんまり変わらないような気もするという。

なので今のコードでもアリかなーと個人的には思います。
(強いて言うなら
・Damageメソッド内のforはWeaponクラスに移したい(同じコードが複数箇所にあるのは極力減らしたい)
・WeaponクラスOnTriggerEnter2D内でnewしているリストはクラス変数へ
というぐらいかと)

投稿2018/06/05 11:01

sakura_hana

総合スコア11427

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

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

kknk

2018/06/06 22:25

回答ありがとうございます。 具体的なコードを書いていただきとても参考になりました! 属性クラスを作りDamageableインターフェースを抽象クラスにして属性ごとのダメージ処理を書いておきデフォルトじゃない処理をしたい場合にだけ継承先のクラスに処理を書いた方が自分の書いたコードよりもシンプル?スッキリしている?うまく言えませんが良いと思いました。こちらのコードを参考に属性クラスを作りDamageableクラスを抽象クラスで継承させるやり方で書き直してみようと思います。勉強になりました。ありがとうございます。 またよろしくお願いします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問