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

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

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

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

Q&A

解決済

2回答

626閲覧

[C++] [ECS Archetype] 確保したメモリに実体を割り当てる方法が知りたい

samidare_chan

総合スコア18

C++

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

0グッド

0クリップ

投稿2023/09/25 09:50

質問内容

提示画像のComponent Data 部ですが現状はコンポーネントがお互い独立している状況での処理の作りになってしまい、あるコンポーネントが別のコンポーネントの参照がほしい場合や高速に移動する物体同士の当たり判定で少しずつ移動してお互いが当たるまでの座標を計算する場合等に対応していません。この状況に対処しつつかつキャッシュヒット率を上げるにはどうすればいいのでしょうか?

知りたこと

あるコンポーネントが別のコンポーネントの参照がほしい場合や高速に移動する物体同士の当たり判定で少しずつ移動してお互いが当たるまでの座標を計算する場合等に対応させるために、離れた場所のメモリを近くに移動させる?、などの方法などどうやって行うのでしょうか?確保したメモリに実体を割り当てる方法が知りたいです

現状

図のように独立したコンポーネントの場合のみ対応

考えたこと

下の図のようにお互いが独立している場合は図のようにシステムが処理をすればいいのですがあるコンポーネントが別のコンポーネントの参照が欲しい場合にその離れたメモリの場所に移動してしまうのでキャッシュヒット率が落ちるためやりたいこととは違います。

また、物理演算ではありませんが、高速に移動する物体同士の当たり判定を行う場合は低速に移動させてお互いが衝突するまで少しずつ処理を繰り返すと思うのですがその際も上と同じように離れたメモリに移動してしまうのでキャッシュヒット率が下がるのでやりたいこととは違います。

以下の提示コードのようにmemset()を使ってmalloc()で確保したメモリを利用した型で利用済みにすると考えたのですがこれはなんかやり方が違うと思います

ソースコード

cpp

1#include <iostream> 2#include <bitset> 3#include <string> 4#include <tuple> 5#include <typeinfo> 6#include <vector> 7#include <stdarg.h> 8#include <stdlib.h> 9#include <cstring> 10 11class Component 12{ 13public: 14 Component() 15 { 16 17 } 18private: 19}; 20 21class Transform : public Component 22{ 23public: 24 Transform() : Component() 25 { 26 27 } 28}; 29 30class SpriteRenderer : public Component 31{ 32public: 33 SpriteRenderer() : Component() 34 { 35 36 } 37}; 38 39class BoxCollision : public Component 40{ 41public: 42 BoxCollision() : Component() 43 { 44 45 } 46}; 47 48 49class Entity 50{ 51public: 52 Entity() 53 { 54 55 } 56}; 57 58class EntityManager 59{ 60public: 61 EntityManager() {} 62 63 64 void AddEntity() 65 { 66 67 68 } 69 70private: 71 72 73}; 74 75struct Player_Archetype 76{ 77 Transform transform; 78 BoxCollision boxCollision; 79 SpriteRenderer spriteRenderer; 80}; 81 82 83struct Item_Archetype 84{ 85 Transform transform; 86 SpriteRenderer spriteRenderer; 87}; 88 89char* data = (char*)malloc(sizeof(Player_Archetype) + sizeof(Item_Archetype) * 2); 90 91int main() 92{ 93 memset(data,sizeof(Player_Archetype),data[0]); 94 95 96 97 return 0; 98}

図について

図はchatGDTの回答を元にしたECS Archetypeの関係図です
Coomponent Data にはコンポーネントの実体がメモリに連続して並んで格納されています。

関係図

イメージ説明

ChatGDT 回答

ECS(Entity-Component-System)は、ゲーム開発やシミュレーションなどのコンピュータプログラムで使用されるアーキテクチャパターンです。このアーキテクチャでは、プログラム内のすべてのデータと振る舞いがエンティティ、コンポーネント、システムという3つの主要な概念に基づいて構成されます。 C++でECSアーキタイプを実装する場合、次のように概念を説明できます: エンティティ(Entity): ゲーム内のオブジェクトやエンティティを表します。これは通常、識別子や一意のIDで表され、エンティティにはコンポーネントがアタッチされます。エンティティ自体は通常、データを持たず、単なる識別子です。 コンポーネント(Component): エンティティの特性や振る舞いを定義する部品です。例えば、ゲーム内のエンティティが位置、速度、描画情報を持つ必要がある場合、それぞれの特性をコンポーネントとして定義します。C++では、これらのコンポーネントは通常、データ構造(クラスまたは構造体)として実装されます。 システム(System): ゲーム内のロジックや振る舞いを処理するコンポーネントです。システムはエンティティにアタッチされたコンポーネントを操作し、ゲームの進行や振る舞いを制御します。C++でシステムを実装する際には、エンティティとそのコンポーネントに対して操作を行うためのコードを記述します。 ワールド(World)は、ECSアーキテクチャ内でこれらのエンティティ、コンポーネント、およびシステムが相互作用するコンテキストを指します。ワールドは通常、ゲームエンジンやアプリケーションの中心的な部分で、エンティティの生成、削除、コンポーネントの追加、システムの更新など、ECSアーキテクチャの要素を管理します。 C++でECSアーキタイプを実装する場合、ワールドはエンティティ、コンポーネント、システムの作成、管理、および相互作用を担当するクラスや構造体として実装されることがあります。ワールドは通常、ゲーム内のすべてのエンティティとそれらのコンポーネントを管理し、ゲームの進行を制御する中心的な要素です。

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

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

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

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

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

fana

2023/09/26 02:12

正直,何が問題なのかわかりません. ChatGPT(ですよね?)の回答とかいう話には「キャッシュがどうの~」いう話は全く出てきていないように見えますし, > 高速に移動する物体同士の当たり判定を行う場合は低速に移動させてお互いが衝突するまで少しずつ処理を繰り返す なる話が「キャッシュ~」いう話にどう繋がっているのかも不明です. (全ての物体が低速だったならば「キャッシュ~」の問題は起きない,という話なのですか?)
guest

回答2

0

(いろいろと突っ込まれるであろうことを承知で書いてみる)

"ECS" とかいうのをちょっとググってみた雰囲気としては
「コンポーネントとかいう単位のデータを一か所に纏め置きすれば,纏め置きしない場合と比べてメモリが局所化しないから処理が早いハズ」
みたいなことを謳っている話なのかな,と見えます.
(他に「継承じゃなくて委譲でどうの~」いう方向の話も見かけましたが,本件に関してはそっちの話をしているわけではないと思う.)

そういう効能を所望しているのであれば,その「纏め置き」の仕方というのを「あなたが実際に作る物の都合を鑑みた(最も効率的になると思われる)置き方」にすれば良いのではないでしょうか.

「当たり判定」が最もこの観点で厄介なのだ,というのであれば,【 最初から 当たり判定が効率的になる何らかの形で纏めて置く】ことを考えることになるのではないでしょうか.
(そのせいで他処理の際にはちょっと効率が下がるかもだけど,全体としての効率を上げる,っていう方向.)

具体的に何をどうすれば効率的になるのかは知りませんが……
例えば,固定的に単純な一本の配列に纏めるのではなく,何らかの空間的な位置に基づいたグループに纏めるとか?

投稿2023/09/26 03:16

編集2023/09/26 04:06
fana

総合スコア12138

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

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

0

ベストアンサー

いま実際にパフォーマンスの問題が出ていて、メモリの局所性の悪さが主因であると断定しているのでしょうか?

もしそうなら、placement new を駆使して頑張ってください。
もしパフォーマンスの問題が出ていないのなら、今から何か対策をする必要はありません。問題が出てから対処をしましょう。
もしパフォーマンスの問題が出ているがメモリの局所性が主因かどうかはわからないなら、まずはアルゴリズムやデータ構造の改善をしましょう。メモリの局所性を気にするのはその後でいいと思います。

投稿2023/09/25 23:47

int32_t

総合スコア21906

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.32%

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

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

質問する

関連した質問