Массив содержащий компоненты игрового обьекта
| |
zaicev9797 | Дата: Пятница, 14 Июня 2019, 20:26 | Сообщение # 1 |
AbRaKaDaBrA
Сейчас нет на сайте
| как можно сделать чтоб внутри класса GameObject можно было хранить массив или список наследников класса Component (например TransfromComponent : public Component или Collider : public Component и т.д.) У Component есть метод Update. соответственно я хочу чтоб GameObject который содержит набор экземпляров разных наследников Component мог вызывать их Update. Как такое можно сделать?
В данный момент, если я придумываю новый компонент который можно было бы прицепить к GameObject мне приходится прописывать однотипные методы которые отличаются только типом компонента, а так же отдельные поля для хранения каждого типа компонента.
Короче выглядит это вот так, и что то мне подсказывает, что это лютая дичь
Код class GameObject{ TransformComponent *transform; Body *body; Collider *collider; DrawComponent *draw; Spacecraft *spacecraft; ParticleController *particleController; ParticleSystem *particleSystem; BackgroundController *backgroundController; FireController *fireController; Button *button; TextWindow *textWindow; FireLight *fireLightController; WeaponLight *weaponLightController; ExplosionLight *explosionLightController; Asteroid *asteroidController; ExplosionController *explosionController; PlayerController *playerController; EngineParticleController *engineParticleController; Bullet *bulletController; Weapon *weaponController; AsteroidSpawner *asteroidSpawnerController; bool destroy = false; String tag; public: GameObject() { transform = NULL; body = NULL; collider = NULL; draw = NULL; spacecraft = NULL; particleSystem = NULL; particleController = NULL; backgroundController = NULL; fireController = NULL; button = NULL; textWindow = NULL; fireLightController = NULL; asteroidController = NULL; explosionController = NULL; playerController = NULL; bulletController = NULL; weaponController = NULL; weaponLightController = NULL; explosionLightController = NULL; asteroidSpawnerController = NULL; }
void SetTransform(TransformComponent *_trnasform) { transform = _trnasform; tag = transform->GetTag(); } void SetDrawComponent(DrawComponent *_draw){draw = _draw;} void SetCollider(Collider *_collider){collider = _collider;} void SetBody(Body *_body){body = _body;} void SetSpacecraft(Spacecraft *_spacecraft){spacecraft = _spacecraft;} void SetParticleController(ParticleController *_particleController){particleController = _particleController;} void SetBackgroundController(BackgroundController *_backgroundController){backgroundController = _backgroundController;} void SetButtonController(Button *_button){button = _button;} void SetParticleSystem(ParticleSystem *_particleSystem){particleSystem = _particleSystem;} void SetFireController(FireController *_fireController){fireController = _fireController;} void SetTextWindowController(TextWindow *_textWindow){textWindow = _textWindow;} void SetFireLitghtController(FireLight *_fireLightController){fireLightController = _fireLightController;} void SetAteroidController(Asteroid *_asteriodController){asteroidController = _asteriodController;} void SetExplosionController(ExplosionController *_explosionController){explosionController = _explosionController;} void SetPlayerController(PlayerController *_playerController){playerController = _playerController;} void SetEngineParticleController(EngineParticleController *_engineParticleController){engineParticleController = _engineParticleController;} void SetBulletController(Bullet *_bulletController){bulletController = _bulletController;} void SetWeaponController(Weapon *_weapon) { weaponController = _weapon; } void SetWeaponLightController(WeaponLight *_weaponLight) { weaponLightController = _weaponLight; } void SetExplosionLightController(ExplosionLight *_explosionLight) { explosionLightController = _explosionLight; } void SetAsteroidSpawnerController(AsteroidSpawner *_asteroidSpawner) { asteroidSpawnerController = _asteroidSpawner; }
TransformComponent* GetTransformComponent(){return transform;} DrawComponent* GetDrawComonent(){return draw;} Collider* GetCollider() {return collider;} Body *GetBody(){return body;} Spacecraft *GetSpacecraft(){return spacecraft;} ParticleController *GetParticleController(){return particleController;} BackgroundController *GetBackgroundController(){return backgroundController;} Button *GetButton() { return button; } TextWindow *GetTextWindow(){return textWindow;} FireLight *GetFireLightController(){return fireLightController;} Asteroid *GetAsteroidController(){return asteroidController;} ExplosionController *GetExplosionController(){return explosionController;} PlayerController *GetPlayerController(){return playerController;} EngineParticleController *GetEngineParticleController(){return engineParticleController;} bool GetDestroy(){return destroy;} ParticleSystem *GetParticleSystem(){return particleSystem;} FireController *GetFireController(){return fireController;} Bullet *GetBulletController(){return bulletController;} Weapon *GetWeaponController() { return weaponController; } WeaponLight *GetWeaponLightController() { return weaponLightController; } ExplosionLight *GetExplosionLightController() { return explosionLightController; } AsteroidSpawner *GetAsteroidSpwnerController() { return asteroidSpawnerController; } String *GetTag(){return &tag;} void Update(RenderWindow &window) { //printf("\n\n%s \n", transform->GetName().toAnsiString().c_str()); if (backgroundController != NULL){backgroundController->Update();} if (textWindow != NULL){textWindow->Update(window);} if (button != NULL){button->Update(window);} if (body != NULL){body->Update();} if (spacecraft != NULL){spacecraft->Update();} if (particleSystem != NULL){particleSystem->Update();} if (particleController != NULL){particleController->Update();} if (fireController != NULL){fireController->Update();} if (fireLightController != NULL){fireLightController->Update();} if (asteroidController != NULL){asteroidController->Update();} if (explosionController != NULL){explosionController->Update();} if (playerController != NULL){playerController->Update();} if (engineParticleController != NULL){engineParticleController->Update();} if (bulletController != NULL){bulletController->Update();} if (weaponController != NULL) { weaponController->Update(); } if (weaponLightController != NULL) { weaponLightController->Update(); } if (explosionLightController != NULL) { explosionLightController->Update(); } if (asteroidSpawnerController != NULL) { asteroidSpawnerController->Update(); } if (draw != NULL){draw->Draw(window);} }
void Destroy() { if (transform != NULL){transform->Destroy();} if (collider != NULL){collider->Destroy();} if (draw != NULL){draw->Destroy();} if (body != NULL){body->Destroy();} if (spacecraft != NULL){spacecraft->Destroy();} if (particleController != NULL){particleController->Destroy();} if (particleSystem != NULL){particleSystem->Destroy();} if (backgroundController != NULL) { backgroundController->Destroy(); } if (button != NULL){button->Destroy();} if (textWindow != NULL){textWindow->Destroy();} if (fireController != NULL){fireController->Destroy();} if (asteroidController != NULL){asteroidController->Destroy();} if (fireLightController != NULL){fireLightController->Destroy();} if (explosionController != NULL){explosionController->Destroy();} if (playerController != NULL){playerController->Destroy();} if (engineParticleController != NULL){engineParticleController->Destroy();} if (bulletController != NULL){bulletController->Destroy();} if (weaponController != NULL) { weaponController->Destroy(); } if (weaponLightController != NULL) { weaponLightController->Destroy(); } if (explosionLightController != NULL) { explosionLightController->Destroy(); } if (asteroidSpawnerController != NULL) { asteroidSpawnerController->Destroy(); } destroy = true; } };
проект Mysterious Space. The losted moment
Сообщение отредактировал zaicev9797 - Пятница, 14 Июня 2019, 20:27 |
|
| |
drcrack | Дата: Пятница, 14 Июня 2019, 21:15 | Сообщение # 2 |
старожил
Сейчас нет на сайте
| Чел, вот глядя на этот код, могу тебе с уверенностью сказать, что тебе рано писать свой движок Кроме того, что ты не готов (серьезно, не знаешь про виртуальные методы?), в юнити очень многое завязано на рефлексию и сделать аналогичный функционал на чистом С++ для С++ скриптов у тебя вряд ли получится
|
|
| |
zaicev9797 | Дата: Пятница, 14 Июня 2019, 21:40 | Сообщение # 3 |
AbRaKaDaBrA
Сейчас нет на сайте
| про виртуальные методы знаю. Но все дело в отсутствии практики с ними. Вроде уже на втором курсе, и половине одногрупников курсачи на сях писать умудряюсь, а вот виртуальными методами так и не научился пользоваться. В общем то я за помощью сюда и прибыл. Точно не за отправлением в детский садик. Вот если покажете пример решения и улучшения такого говнокода, вот это будет действительно круто.
проект Mysterious Space. The losted moment
Сообщение отредактировал zaicev9797 - Пятница, 14 Июня 2019, 21:41 |
|
| |
drcrack | Дата: Пятница, 14 Июня 2019, 22:37 | Сообщение # 4 |
старожил
Сейчас нет на сайте
| возьми любой учебник по C++ и почитай главу про ООП, там все обьясняется с примерами
PS
Цитата Точно не за отправлением в детский садик. если к тебе подойдет ребенок с игрушечным бульдозером и совочком для песка, и скажет что хочет построить 100-этажный небоскреб, ты ему начнешь обьяснить как это сделать или отправишь обратно в детский садик?
Сообщение отредактировал drcrack - Пятница, 14 Июня 2019, 22:44 |
|
| |
pixeye | Дата: Пятница, 14 Июня 2019, 23:12 | Сообщение # 5 |
Red Winter Software
Сейчас нет на сайте
| Цитата zaicev9797 ( ) Вроде уже на втором курсе, и половине одногрупников курсачи на сях писать умудряюсь, Не путай продакшен код с курсачом который пишется чтобы выброситься. То что ты можешь университетские задачки на сях не говорит ни о чем.
Повторять юнитивскую архитектуру игровой логики так себе. Она не самая удачная и обусловлена тем что юнити нацелены на макс широкую аудиторию и жанровую направленность.
Неочевидны твои задачи. Ты пишешь движок или игру? Если игру то тебе действительно нужен настолько большой уровень абстракции ?
ACTORS - мой фреймворк на Unity Until We Die - игра над которой работаю
Сообщение отредактировал pixeye - Суббота, 15 Июня 2019, 00:05 |
|
| |
zaicev9797 | Дата: Суббота, 15 Июня 2019, 05:59 | Сообщение # 6 |
AbRaKaDaBrA
Сейчас нет на сайте
| Цитата drcrack ( ) ООП, там все обьясняется с примерами Дак вот читал же ведь. И в унике читали курс по ООП, но как правило примеры и там и там ограничиваются двумя - тремя классами с простейшими примерами типа банковских счетов, по которым сложно представить как работает тот или иной тип классов или паттерн. Может плохо искал, но вот не видел я более крупных примеров, где разрабатывается более менее обьемная взаимосвязанная система.Цитата pixeye ( ) Если игру то тебе действительно нужен настолько большой уровень абстракции ? А вот это уже хороший вопрос, может и действительно не нужен, я сам еще в раздумиях так сказать. С одной стороны хочется разобраться в том, как это у крупных дядек работает, с другой стороны супер навороченых игр я вроде тоже не собираюсь делать (покрайней мере не на самописных велосипедах)
проект Mysterious Space. The losted moment
|
|
| |
afq | Дата: Суббота, 15 Июня 2019, 09:20 | Сообщение # 7 |
Разработчик
Сейчас нет на сайте
| Цитата если к тебе подойдет ребенок с игрушечным бульдозером и совочком для песка, и скажет что хочет построить 100-этажный небоскреб, ты ему начнешь обьяснить как это сделать или отправишь обратно в детский садик? Хахаха zaicev9797, я тут набрасал код на c++. Не знаю, поможет ли он тебе чем нибудь. Но мне стала интересна твоя задачка. Я исходил из того что вроде все объекты в unity исходят из gameobject. Вот как я реализовал это.
Код #pragma once #include "mem.h" #include "base.h" #include "two.h"
class Object { public: Object ( ) { mem = nullptr; } void set_attr ( Base *b, int i ) { Base *base = b->get(); base->set ( i ); } int get_attr ( Base *b ) { return b->get_int(); } protected: private: Mem *mem; Two *two;
};
Видишь я сделал один set_attr, и он в зависимости от типа присваивает переменные либо mem, либо two. В main это выглядит вот так.
Код #include <stdio.h> #include "object.h" #include "mem.h" #include "base.h" #include "two.h"
int main ( ) { Object *obj = new Object ( ); Mem *mem = new Mem ( ); Two *two = new Two ( );
obj->set_attr ( mem, 4 ); obj->set_attr ( two, 8 );
printf ( "1: %d\n", obj->get_attr ( mem ) ); printf ( "2: %d\n", obj->get_attr ( two ) ); }
Первый выведет 4, потому что для mem я так записал, а второй выведет 8. Вообще это работает, если типы каждого вида есть в единственном экземпляре. Может мой код и далёк от совершенства, но это первое что мне пришло в голову. Вот остальной код.
Код #pragma once
class Base { public: Base ( ) { } virtual void set ( int i ) = 0; virtual Base *get ( ) = 0; virtual int get_int ( ) = 0; private: protected: };
Здесь я использовал виртуальные функции, чтобы в произовдном классе использовать их. Из-за того, что в base определены эти виртуальные методы, а в производном их решение, я могу делать так.
Код void set ( Base &m ) { printf ( "%d\n", m.get_int ( ) ); } Mem mem; set ( mem );
И вызовется код именно mem а не base. Ну код get_int ( ). Ладно это был пример, если ты не знаешь как использовать виртуальные функции. Теперь далее.
Код #pragma once #include "base.h"
class Mem : public Base { public: Mem ( ) { } void set ( int i ) { this->i = i; } Mem *get ( ) { Mem *m = this; return m; } int get_int ( ) { return i; } private: int i; protected: };
Здесь я переопределяю вызов get, чтобы он возвращал тот тип, который надо.
Код #pragma once #include "base.h"
class Two : public Base { public: Two ( ) { } void set ( int i ) { this->i = i; } Two *get ( ) { Two *m = this; return m; } int get_int ( ) { return i; } protected: private: int i; };
Здесь тоже переопределяю метод get.
Надеюсь тебе понятно. Мне понравилось моё решение, надеюсь и тебе тоже. Попробуй реализовать это в unity, Тогда не придётся писать для каждого атрибута setter и getter.Добавлено (15 Июня 2019, 09:51) --------------------------------------------- АААА БЛИН, я какую то фигню написал, я же не присвоил атрибутам object значения. ааааа. Добавлено (15 Июня 2019, 10:02) --------------------------------------------- zaicev9797, в android studio например для каждого свойства класса можно с помощью команды задать геттеры и сеттеры. Может и в твоей ide можно такое сделать? Добавлено (15 Июня 2019, 10:41) --------------------------------------------- zaicev9797 всё, я смог реализовать это на c++, только пока вот так.
Код #pragma once #include <map> #include <string> #include <iostream> #include "mem.h" #include "base.h" #include "two.h"
class Object { public: Object ( ) { map[typeid( Mem ).name() ] = new Mem ( ); map[typeid( Two ).name() ] = new Two ( ); } void set_attr ( Base *b, int i ) { Base *base = map [ typeid( *b->get()).name() ]; base->set ( i ); } int get_attr ( Base *b ) { return map[typeid(*b->get()).name()]->get_int(); } protected: private: std::map<std::string, Base*> map;
};
Это изменения в коде. То есть тебе свойства так и так придётся создать. Их я занёс в map. С помощью typeid я узнаю имя класса. Далее в main вот так.
Код #include <stdio.h> #include "object.h" #include "mem.h" #include "base.h" #include "two.h"
int main ( ) { Object *obj = new Object ( ); Mem *mem = new Mem(); Two *two = new Two();
obj->set_attr ( mem, 4 ); obj->set_attr ( two, 8 );
printf ( "1: %d\n", obj->get_attr ( mem ) ); printf ( "2: %d\n", obj->get_attr ( two ) ); printf ( "3: %d\n", obj->get_attr ( mem ) ); }
По другому я не смог сделать, то есть надо и здесь и здесь создавать объекты. Но в твоём случае там надо получить ссылку типа такого вроде GetComponent<typename>(). Чтобы получить имя класса, указателя не достаточно, надо проверять целый класс.Добавлено (15 Июня 2019, 10:43) --------------------------------------------- Думаю в c# тоже можно узнать имя класса.
|
|
| |
pixeye | Дата: Суббота, 15 Июня 2019, 10:58 | Сообщение # 8 |
Red Winter Software
Сейчас нет на сайте
| Цитата zaicev9797 ( ) А вот это уже хороший вопрос, может и действительно не нужен, я сам еще в раздумиях так сказать. С одной стороны хочется разобраться в том, как это у крупных дядек работает, с другой стороны супер навороченых игр я вроде тоже не собираюсь делать (покрайней мере не на самописных велосипедах)
*****во порой у крупных дядек работает XD Хочешь C/C++ код крупных игр смотреть смотри тогда сорсы кваки 3, думов и прочая. Они давно уже выложены. Юнити пилят годами штат прогеров. Задача юнити - привлечь больше разработчиков и сделать их движок самым популярным и зарабатывать деньги . Многие их решениях это попытка выразить сложное через простое идя на кучу компромиссов.
Как разработчику игр тебе в общем-то должно быть пофиг. Ты берешь инструмент по своим скилам и выжимаешь максимум из него. ( Юнити замечательный двиг и много классных игр было сделано на нем ) Если тебе больше нра движки то просто устройся на работу в юнити : )
Ну и иди от простого к сложному.
ACTORS - мой фреймворк на Unity Until We Die - игра над которой работаю
|
|
| |
drcrack | Дата: Суббота, 15 Июня 2019, 11:08 | Сообщение # 9 |
старожил
Сейчас нет на сайте
| Цитата По другому я не смог сделать, то есть надо и здесь и здесь создавать объекты. Но в твоём случае там надо получить ссылку типа такого вроде GetComponent<typename>(). Чтобы получить имя класса, указателя не достаточно, надо проверять целый класс. Добавлено (15 Июня 2019, 10:43) --------------------------------------------- Думаю в c# тоже можно узнать имя класса. кажеца ты начинаешь понимать что без рефлексии и дженериков тебя ждет только боль и страдания при попытке повторить архитектуру юнити на с++ вот бы тс еще понял
Сообщение отредактировал drcrack - Суббота, 15 Июня 2019, 11:09 |
|
| |
afq | Дата: Суббота, 15 Июня 2019, 12:53 | Сообщение # 10 |
Разработчик
Сейчас нет на сайте
| zaicev9797, а ты на c++ это делал, я думал что ты на c# на unity делаешь. Тот метод, который я написал, он медленный, потому что ассоциативный массив. Лучше создавать все свойства и методы. Сделай основной объект с виртуальными функциями. Наследуй каждый объект от этого объекта. А дальше думай ещё что нибудь.
Добавлено (15 Июня 2019, 13:19) --------------------------------------------- Всё, теперь можно создавать объекты, только в main.
Код #pragma once #include <map> #include <string> #include <iostream> #include "mem.h" #include "base.h" #include "two.h"
class Object { public: Object ( ) { map[typeid( Mem ).name() ]; map[typeid( Two ).name() ]; } void set_attr ( Base *b, int i ) { map [ typeid( *b->get()).name() ] = b->get(); Base *base = b->get(); base->set ( i ); } int get_attr ( Base *b ) { return map[typeid(*b->get()).name()]->get_int(); } protected: private: std::map<std::string, Base*> map;
};
Сообщение отредактировал afq - Суббота, 15 Июня 2019, 13:20 |
|
| |
|