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

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

ただいまの
回答率

90.47%

  • C++

    3601questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • Win32 API

    226questions

    Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

  • DirectX

    72questions

    DirectX(ダイレクトエックス)は、 マイクロソフトが開発したゲーム・マルチメディア処理用のAPIの集合です。

C++でゲーム開発する際の設計について

受付中

回答 4

投稿

  • 評価
  • クリップ 6
  • VIEW 3,251

tiwatiwa

score 57

C++で3Dゲーム開発を行っています。

現在、すべてをクラスとして設計(グローバル変数は禁止の自分ルール)しているのですが、プログラム内の変数や引数がC++のスマートポインタだらけになってしまっています。(shared_ptrとweak_ptrが大半です。)

スマートポインタを使って設計を行った場合にこうなるのは仕方のないことなのでしょうか?
また、スマートポインタを使わずにもっとバグが出にくくできたり、保守が容易になるような設計方法がありましたら、ご教授お願いします。

例えば、プログラム内の変数やクラスのポインタを持つだけのクラスを作って、それをクラス間で渡すことで引数の数を減らしたり、他クラスへのアクセスが容易になると考えたのですが、信頼性やプロから見た際の見栄えはどうなのかな?と思っています。(スマートポインタを使えば大丈夫なのかな?)

また、少し論点がずれるくらいは問題ないので、自分はこうやってるよ!みたいなことがあればよろしくお願いします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

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

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

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+4

C++のスマートポインタ(shared_ptrweak_ptr)は、インスタンスの所有権(ownership)を管理するものです。

C++プログラムにて所有権を扱う方法として、その他には下記が考えられます。いずれもshared_ptr<T>weak_ptr<T>より「軽量」な仕組みですから、必要に応じて利用検討してください。

(1) (スマートポインタではない)値型Tとしてメンバ変数を保持する。保持クラスのインスタンス生存期間=対象インスタンスの生存期間であり、保持クラスが対象インスタンスを所有する場合はこれがベストです。
(2) 関数の引数型として、スマートポインタの代わりに参照型(T&const T&)をとる。インスタンスの所有権は関数呼び出し元に残っており、関数呼び出し中(≒呼び出し元は待機状態)だけインスタンスにアクセスさせるという考え方です。
(3) 所有権を共有する必要がなければ、shared_ptr<T>ではなくunique_ptr<T>を使うべきです。unique_ptr<T>の方が(アクセス時間・メモリ専有量ともに)実行時オーバーヘッドが小さくなります。なお、必要に応じてunique_ptr<T>からshared_ptr<T>へと変換可能です。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

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

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

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+2

あくまでも自分の場合ですが…

ポインタが増えるのは仕方ないのですが、なるべくクラス内に隠蔽して外に出さない仕組みを作ります。

関数の引数は、操作対象のオブジェクトへの参照とオプションの2つ3つで賄えることが多いので、引数が多くなったら減らせないか考えます。

それと同時に、ゲームの場合、インスタンスがひとつで良いものが多いので、その場合はあまりこだわらずにグローバルにします。グローバル変数はちょっと嫌なので、静的メンバなどで。これで引数で引き回す量が減ります。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

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

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

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/06/25 19:00

    >ポインタが増えるのは仕方ないのですが、なるべくクラス内に隠蔽して外に出さない仕組みを作ります。
    やっぱり「なるべく」になってしまうのはしょうがないのでしょうか...

    キャンセル

0

私はゲームを作っていないので、文章中の例が的外れかもしれませんが
例えば、プログラム内の変数やクラスのポインタを持つだけのクラスを作って、それをクラス間で渡すことで引数の数を減らしたり、他クラスへのアクセスが容易になると考えたのですが、信頼性やプロから見た際の見栄えはどうなのかな?と思っています。(スマートポインタを使えば大丈夫なのかな?) 
引数の設定が同じなら結果が必ず同じ、という場合構造体にまとめることはあります。
例えば、細かく装備品をカスタマイズするためのメソッドを作りたい!という場合には武器カスタマイズに関する注文書のイメージで構造体にまとめて渡します。
※RESTful APIと近いかな


他に引数を減らすためにしていることは、纏められる情報は纏めること、クラス自体を受け渡すのではなく、クラスのメソッドを呼び出すようにリファクタリングすることです。
簡単な例ですが、あるキャラクターの座標を変更する関数UpdatePosition(Character *character, int x, int y) があったとします。

これは、まず座標を構造体struct Point { int X, int Y } を作って短くできるでしょうし
UpdatePosition(Character *character, Point point)

UpdatePosition自体をCharacterクラスのメンバに含めることもできます。
void Character::UpdatePosition(Point point);
※座標情報(状態)をCharacterに持つべきではない場合もあるので、その場合は座標+キャラクターを管理するラップクラスを作ってそちらに委任します。

直接メソッドを呼び出す形式にできれば、クラス内の変数にアクセスする必要性が無くなりますし、メンバが晒されない=外部参照が減るということですから、weak_ptrも減るかもしれません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

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

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

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

3Dゲーとのことなので、速度やフレームレートの安定が重要であるという前提で考えると
何でもかんでもスマートポインタにしとこう、というのはちょっとマズイかもしれません。

MMORPGやオープンワールドゲームのように、必要になるリソースをしぼれない
(ワールドマップで遊んでいる最中にVRAMにロードしてないテクスチャが必要になる、新しいキャラクタが現れるなど)場合は仕方ないですが、
基本的にゲームはプレイ中に画面がガクつかない方がいいですよね。
なので基本的にプレイ中のヒープ確保は厳禁です。キャラクタクラス等はロード終了前に全て確保されているべきです。

同時に、テクスチャ等のGPUリソースも所有権を曖昧にせず、リソースを管理するクラスに一元管理させて
ロード画面のときに必要なものを全て読み、VRAMの空きに応じて不要なものを破棄すべきです。
あとリソースとゲーム内の概念のクラス(キャラクタ等)は分離してますでしょうか?
一般的には、リソースとキャラクタ等は癒着させない方がいいです。

決してスマートポインタを使うなという話ではないのですが、その辺の事情を加えれば、ご自身の開発に適したスマートポインタの種類、あるいは管理方法が浮かんでくるのではないでしょうか。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

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

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

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

関連した質問

  • 解決済

    ポインタで実現する文字列

    細かい事なのですが、下のコードでは"123"という文字列リテラルが生まれてから、そのアドレスを示すのがptrポインタという理解で正しいですか? ポインタが文字列リテラルのどちらが先

  • 解決済

    構造体のポインタがわからない

    #include <stdio.h> #include<stdlib.h> struct name {    int a;    float b;    char c[30]; }

  • 解決済

    アドレスが等しくならない ポインタ

    このコードでptrポインタが示すアドレスとnumberのアドレスが同じになりません。 int *ptr=new int()が原因なのかなと考えているのですが、なぜアドレスが同じにな

  • 解決済

    ポリモーフィズムの仕組み

    ポリモーフィズムの実装で、原型クラスのポインタを使って、なぜ派生クラスを指し示すようになったのでしょうか? class Girl;public Humanというのは物理的にどのよ

  • 受付中

    C++のインスタンスについて

    JAVA開発経験有のC++初心者です。 C++で仮にTestクラスのインスタンスを作成しメソッドを実行する場合下記の方法があるかと思います。 ① Test inst;

  • 解決済

    デストラクタが呼ばれない理由が知りたい

    newでインスタンス化するメソッドをポインタから呼び出すような以下のクラス: #include <iostream> class Test{ public:

  • 解決済

    メンバ変数をポインタで持つか実体で持つか

    メンバ変数を実体で持つか、ポインタで持つか、で悩んでおります。 ゲームに登場するオブジェクトの基底クラスを作成しているのですが、 例えば、下記のような場合、Vector3、Bo

  • 解決済

    C++ アドレスの代入

    出題された問いを解いている最中で詰まってしまったので、質問させていただきます。 typedef unsigned char BYTE; // 問題で決まっている定数 #def

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

  • C++

    3601questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

  • Win32 API

    226questions

    Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

  • DirectX

    72questions

    DirectX(ダイレクトエックス)は、 マイクロソフトが開発したゲーム・マルチメディア処理用のAPIの集合です。