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

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

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

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

デザインパターン

デザインパターンは、ソフトウェアのデザインでよく起きる問題に対して、解決策をノウハウとして蓄積し再利用出来るようにした設計パターンを指します。

Unity

Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。

解決済

UnityとC#の単一責任の原則の学習教材に於ける正しい適用方法がわからない

chawanmushi
chawanmushi

総合スコア11

C#

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

デザインパターン

デザインパターンは、ソフトウェアのデザインでよく起きる問題に対して、解決策をノウハウとして蓄積し再利用出来るようにした設計パターンを指します。

Unity

Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。

1回答

0グッド

0クリップ

685閲覧

投稿2022/10/17 07:11

前提

UnityとC#の勉強をしています。
Githubにある、ゲーム開発におけるデザインパターンの学習教材で単一責任の原則を学ぼうと思ったのですが、
単一責任を適用したスクリプトの動作方法がわからず困っています。

実現したいこと

  • 単一責任の原則を適用したコードを動かしたい

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

元コードの場合はオブジェクトにアタッチすることでオブジェクトが移動するのですが、 そのコードに単一責任の原則を適用したコードの場合は、オブジェクトにアタッチするだけではオブジェクトを動かせない。

該当のソースコード

元のコード

C#

1namespace DesignPatterns.SRP 2{ 3 // Even though this class is short, it violates single-responsibility. 4 // Too many things will cause the class to update, and extending the class will be more difficult. 5 6 public class UnrefactoredPlayer : MonoBehaviour 7 { 8 9 [SerializeField] private string _inputAxisName; 10 11 [SerializeField] private float _positionMultiplier; 12 13 private float _yPosition; 14 15 private AudioSource _bounceSfx; 16 17 private void Start() 18 { 19 _bounceSfx = GetComponent<AudioSource>(); 20 } 21 22 private void Update() 23 { 24 float delta = Input.GetAxis(_inputAxisName) * Time.deltaTime; 25 26 _yPosition = Mathf.Clamp(_yPosition + delta, -1, 1); 27 28 transform.position = new Vector3(transform.position.x, _yPosition * _positionMultiplier, transform.position.z); 29 } 30 31 private void OnTriggerEnter(Collider other) 32 { 33 _bounceSfx.Play(); 34 } 35 } 36 37}

適用したコード

C#

1namespace DesignPatterns.SRP 2{ 3 [RequireComponent(typeof(PlayerAudio), typeof(PlayerInput), typeof(PlayerMovement))] 4 public class Player : MonoBehaviour 5 { 6 [SerializeField] private PlayerAudio playerAudio; 7 [SerializeField] private PlayerInput playerInput; 8 [SerializeField] private PlayerMovement playerMovement; 9 10 private void Start() 11 { 12 playerAudio = GetComponent<PlayerAudio>(); 13 playerInput = GetComponent<PlayerInput>(); 14 playerMovement = GetComponent<PlayerMovement>(); 15 } 16 17 } 18}

C#

1namespace DesignPatterns.SRP 2{ 3 // sample code to demo single-responsibility: 4 public class PlayerInput : MonoBehaviour 5 { 6 [SerializeField] private string inputAxisName; 7 8 private void Update() 9 { 10 float delta = Input.GetAxis(inputAxisName) * Time.deltaTime; 11 } 12 } 13} 14

C#

1namespace DesignPatterns.SRP 2{ 3 // sample code to demo single-responsibility 4 public class PlayerMovement : MonoBehaviour 5 { 6 [SerializeField] private float positionMultiplier; 7 private float yPosition; 8 9 private void Update() 10 { 11 transform.position = new Vector3(transform.position.x, yPosition * positionMultiplier, transform.position.z); 12 yPosition++; 13 } 14 } 15}

試したこと

unity内にてinputAxisNameを設定した。
PlayerでplayerInputを使って入力を受け取り、playerMovementのyPositionに代入して動かそうと思ったが、
yPositionがprivateのため、その動かし方は想定してないと判断。

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

Unity 2021.3.11f1
VisualStudio 2022 17.3.5

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

回答1

0

ベストアンサー

教材を見ないと適用後コードの意図が分からないので適当なことしか言えませんが、とりあえず普通にpublicなメソッドとかプロパティを設定しないとどうしようもないと思います。


普通に書けば以下の感じのPlayerクラスだと、いい感じに単一責任原則です。(修正前のコードを見る限り、PlayerはPlayerAudioを知る必要すらありません。)

入力に関する責任も移動に関する責任もPlayer自体は持っていないので簡潔かつ何をやっているのか分かりやすいです。
playerInput.GetInput();はプレイヤーの入力をvector3で返してくれるメソッド、
playerMovement.Move(input)は、入ってきたvector3に沿って移動するメソッドです。

「いや、playerMovement.Move()とかplayerInput.GetInput()とか俺知らねぇんだけど!?」とお思いでしょうが、そこが一番のキモです。
Playerから見たとき、「中で何をやっているか知らないけど、やれって行ったらやってくれることは知ってる」みたいにするのが重要です。

PlayerでplayerInputを使って入力を受け取り、playerMovementのyPositionに代入して動かそうと思ったが、
yPositionがprivateのため

単一責任にするなら、Playerは「playerMovementがyPositionを持っているから、移動するならこいつのyPositionに代入してtransformを動かさないとな」と考えちゃダメです。
それは結局移動のロジックについて、Playerも責任持って関わっていることになるので、単一責任原則ではありません。

C#

1 public class Player : MonoBehaviour 2 { 3 [SerializeField] private PlayerInput playerInput; 4 [SerializeField] private PlayerMovement playerMovement; 5 6 private void Start() 7 { 8 playerInput = GetComponent<PlayerInput>(); 9 playerMovement = GetComponent<PlayerMovement>(); 10 } 11 12 private void Update() 13 { 14 Vector3 input = playerInput.GetInput(); 15 playerMovement.Move(input); 16 } 17 }

投稿2022/10/17 08:15

編集2022/10/17 10:46
UnchFullburst

総合スコア532

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

2022/10/17 08:36依頼された後にこの回答は修正されています

こちらの回答が他のユーザーから「質問に対する回答となっていない投稿」という指摘を受けました。

回答へのコメント

chawanmushi

2022/10/17 12:01

Playerクラスをどう書き換えたら単一責任原則に沿った実装を出来るのかが知りたかったため、 それにぴったりな解答が頂けて本当に嬉しいです。 自分が最初に試したことも単一責任原則に反しているとはまだまだ理解できていないんだと認識出来ました。 丁寧な解答をありがとうございました! 非常に勉強になりましたm(_ _)m

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

ただいまの回答率
86.12%

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

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

質問する

関連した質問

同じタグがついた質問を見る

C#

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

デザインパターン

デザインパターンは、ソフトウェアのデザインでよく起きる問題に対して、解決策をノウハウとして蓄積し再利用出来るようにした設計パターンを指します。

Unity

Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。