最近個人でC#を使ってゲームを作成しているのですが、
たまに「この処理どのクラスに書くべきなのか?」がわからなくなります。
例えば、プレイヤーと敵が存在していて、プレイヤーが敵を攻撃したとします。
プレイヤーが敵を攻撃をする処理はプレイヤークラスに記述すると思いますが
敵のHPを減らす処理や敵のHPが0になったら消滅させる処理はどこに書けばいいのかわからなくなります。
案① プレイヤーが攻撃したからプレイヤークラスに記述するのか
案② 敵のHPや存在に関するから敵クラスに記述するのか
案③ それともまた別のクラスを用意するのか
ちょっと伝わりにくいかもしれません。すみません。
// プレイヤークラス public class Player : MonoBehaviour { Enemy enemy; SystemManagement system; void Start() { enemy = GameObject.Find("Enemy").GetComponent<Enemy>(); system = GameObject.Find("SystemManagement") .GetComponent<SystemManagement>(); } // ボタンクリックしたら実行される void onClick() { // 案① enemy.hp = enemy.hp - 5; if (enemy.hp < 0) { Destroy(enemy.gameObject); } // 案②(enemyクラスでHPが0以下になったら消滅する。) enemy.hp = enemy.hp - 5; // 案③ system.attack(enemy); } }
// 敵クラス public class Enemy : MonoBehaviour { public int hp = 10; void Update() { // 案② if (hp < 0) { Destroy(this.gameObject); } } }
// システムマネジメントクラス public class SystemManagement : MonoBehaviour { public void attack(Enemy enemy) { enemy.hp = enemy.hp - 5; if (enemy.hp < 0) { Destroy(enemy.gameObject); } } }
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/10/26 08:22
2019/10/26 08:30
2019/10/26 09:14
回答3件
0
解決済みの質問相手にゲームプログラミング経験のない門外漢な僕が書くのもおかしな話かもしれませんが、
自分ならこんな風にするといいかもと思いついたので回答として挙げてみます
また、HPと書いてあるのでRPGっぽい戦闘計算を必要とするものを想定します
敵・味方にかかわらず親クラスとして「攻撃する」メソッドと「攻撃を受ける」メソッドを用意します
攻撃するメソッドでは自身の攻撃にかかわる計算(攻撃力や装備・バフ・デバフの影響計算)を行い、攻撃対象の攻撃を受けるメソッドに計算した攻撃値と影響のあるデータ(属性など)を引数として呼び出します
で、攻撃を受けるメソッドでは引数で渡された攻撃相手の攻撃値と影響のあるデータをもとに自身の防御力や攻撃をするメソッドで行ったのと同じように防御力にかかわる計算を行いダメージ計算を行います
そしてHP増減計算メソッドへダメージなので計算した被ダメ値(負の数とするかもしくは回復/被ダメのフラグを渡すか被ダメメソッドと回復メソッドに分けるかはお好みで)を引数にして呼び出し、HP計算を行う
といった流れで行うといいかなーと思います
この形でした理由ですが、
HP計算は確かに攻撃を受ける側の問題ですが、攻撃を与える側にもバフデバフなどの影響要素がある以上攻撃を与える側でも計算を行う必要があるはずです
また、グループ攻撃だったりSPRGやTDのような感じだと範囲攻撃で距離や方向で攻撃力の変化がある場合も考えると攻撃を与える側での細かい計算を与える側のメソッド内で行い、受ける側は受ける攻撃の強さを値として受け取り攻撃を受ける側のメソッドで計算するしかないというところでメソッドがそれぞれに必要であると考えました
と、上記のような感じでどちらか一方に置く必要はないかと思いますので、一つの攻撃処理であってもどこまでの計算はどちら側の領分なのかといったことを考えて適切に設計していけばいいかと思います
蛇足
例えば敵の背中を殴るって行為でも殴る側がどれだけの力で殴るかや殴る人がひょろい場合やムキムキマッチョな人だと同じ全力で殴るでも受けるダメージは違います
また、同じ人が同じ力で敵を殴るとしても相手が痛みに弱い人ならめっちゃ痛がるでしょうし、「鍛えているからだ!」とかいうような人ならあんまり痛くないでしょうし、特殊な訓練を受けた人なら「もっとつよくなぐってくだしゃひぃ~」とか言って回復しているかもしれません
それぞれの違いはそれぞれの内部で保持する情報でしかないのでその影響計算はそれぞれで行うのが妥当って感じですね
そのうえでインターフェースを定義するなり基底クラスを定義するなりして敵だろうが見方だろうが同じ形で計算できるようにすると汎用性が高まるので作るのが楽になるかもと思った次第です
追記:2019年11月02日
コメントで追記した内容をもとに試しで書いてみた
なお、UnityではC#8.0は未実装だと思うので、interface ICharactor
には実装が書けないので、味方クラスと敵クラスすべてに攻撃をするメソッドと攻撃を受けるメソッドを実装する必要があります
C#
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 ICharactor ゆーしゃ = new 味方(); 6 ゆーしゃ.お名前 = nameof(ゆーしゃ); 7 ICharactor つかいっぱー = new 味方(); 8 つかいっぱー.お名前 = nameof(つかいっぱー); 9 10 ICharactor 雑魚えー = new 敵(); 11 雑魚えー.お名前 = nameof(雑魚えー); 12 ICharactor 雑魚びー = new 敵(); 13 雑魚びー.お名前 = nameof(雑魚びー); 14 15 var 倒せたかな = ゆーしゃ.攻撃をする(雑魚えー); 16 if(倒せたかな) 17 { 18 Console.WriteLine($"{ゆーしゃ.お名前}は{雑魚えー.お名前}を倒した!"); 19 } 20 var たげ = 雑魚えー.生きてるの ? 雑魚えー : 雑魚びー; 21 倒せたかな = つかいっぱー.攻撃をする(たげ); 22 { 23 Console.WriteLine($"{つかいっぱー.お名前}は{たげ.お名前}を倒した!"); 24 } 25 } 26 } 27 28 internal interface ICharactor 29 { 30 // これ、C#8.0で処理が書ける 31 // C#8.0未満では{から}までが書けないので各クラスで実装を必ず書く必要がある 32 public bool 攻撃をする(ICharactor target) 33 { 34 return target.攻撃を受ける(攻撃力); 35 } 36 37 //これも同じ 38 public bool 攻撃を受ける(double 攻撃値) 39 { 40 var isDead = Hp <= 攻撃値; 41 42 // イールドは定義できないのでhpのフィールドを変更することができない 43 // かといってhpはげったーのみにしたいので処理が書けない 44 //Hp -= 攻撃値; 45 46 return isDead; 47 } 48 49 public double 攻撃力 { get; } 50 51 public double 防御力 { get; } 52 53 public double Hp { get; } 54 55 public bool 生きてるの { get; } 56 57 public string お名前 { get; set; } 58 } 59 60 public class 味方 : ICharactor 61 { 62 private double atk = 2f; 63 public double 攻撃力 => atk; 64 65 private double vit = 1f; 66 public double 防御力 => vit; 67 68 private double hp = 10f; 69 public double Hp => hp; 70 71 private bool isDead = true; 72 public bool 生きてるの => isDead; 73 public string お名前 { get; set; } 74 75 public bool 攻撃を受ける(double 攻撃値) 76 { 77 var 被ダメ = 攻撃値 - vit; 78 isDead = hp <= 被ダメ; 79 80 hp = isDead ? 0 : hp - 被ダメ; 81 82 return isDead; 83 } 84 85 } 86 87 public class 敵 : ICharactor 88 { 89 private double atk = 1f; 90 public double 攻撃力 => atk; 91 92 private double vit = 2.3f; 93 public double 防御力 => vit; 94 95 private double hp = 1.5f; 96 public double Hp => hp; 97 98 private bool isDead = true; 99 public bool 生きてるの => isDead; 100 public string お名前 { get; set; } 101 102 public bool 攻撃を受ける(double 攻撃値) 103 { 104 var 被ダメ = 攻撃値 - (vit / 2); 105 isDead = hp <= 被ダメ; 106 107 hp = isDead ? 0 : hp - 被ダメ; 108 109 return isDead; 110 } 111 } 112
投稿2019/10/26 14:27
編集2019/11/01 17:13総合スコア1363
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/10/26 14:30
2019/10/26 17:03
2019/11/01 16:09
0
ベストアンサー
恐れ多いですが、「どこに記述すればいいか」に関しては…
基本的にEnemyの「HP」が0になったら「破棄処理」を流したいはずです…。
となると、敵側に記述するのが正しいです…。
プレイヤーはあくまで「攻撃をした」という処理に留め
敵は「外部要因でHPが0になったら消滅する」という処理にするべきです…。
投稿2019/10/26 09:09
総合スコア368
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/10/26 09:14
2019/10/26 09:19
2019/10/26 09:28
2019/10/26 09:39
2019/10/26 09:47
2019/10/26 10:04 編集
2019/10/26 10:08
2019/10/26 10:11
2019/10/26 10:12
2019/10/26 10:13
2019/10/26 10:17
2019/10/26 10:18
2019/10/26 10:21
2019/10/26 10:24
2019/10/26 10:33
2019/10/26 10:38
2019/10/26 10:46
2019/10/26 10:52
2019/10/26 10:53
2019/10/26 10:59
2019/10/26 11:02
2019/10/26 11:04
2019/10/26 11:08
2019/10/26 11:11
2019/10/26 11:18
2019/10/26 11:19
2019/10/26 11:23
退会済みユーザー
2019/10/27 00:03 編集
2019/10/29 17:05
2019/10/29 21:51
退会済みユーザー
2019/11/01 05:12
2019/11/01 17:31
0
案① プレイヤーが攻撃したからプレイヤークラスに記述するのか
案② 敵のHPや存在に関するから敵クラスに記述するのか
案③ それともまた別のクラスを用意するのか
処理を書くべき場所を迷っている時点で,案③です.
その処理は「既存の{プレイヤー,敵}どちらの役割とも言えない」という答えが出ている,ことでしょうから.
(で,後から「やっぱこの処理は敵の領分だったわ」とか明確になったら敵の中に移動させればよい)
(実際にどんな複雑なルールの物を作るのか不明ですが)
攻撃側と被攻撃側とから,攻撃という処理に必要になる情報を取り出しさえすれば,攻撃結果を求めることができるハズです.
その結果情報を被攻撃側に(必要ならば攻撃側にも)伝達してやれば良いでしょう.
(例えば,被攻撃側に「お前のHPを5だけ減らせ」とか)
HPが0になったら消滅させる
に関しては,「俺を消滅させろ(させていいぞ)」という情報を,管理している側に何らかの状態で伝達(あるいは単に表現)すれば良いでしょう.
投稿2019/11/01 05:47
総合スコア11985
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。