Question

Il a été une question sur ce que la conception axée sur les données est, et il y a une article qui est souvent appelé (et je l'ai lu comme 5 ou 6 fois déjà). Je comprends le concept général de cela, en particulier lorsqu'ils traitent avec, par exemple, des modèles 3D, où vous souhaitez garder tous ensemble vertex, et ne pollue pas vos visages avec Normales, etc.

Cependant, j'ai du mal à visualiser la façon dont la conception axée sur les données pourraient fonctionner pour quoi que ce soit, mais la plupart des cas insignifiants (modèles 3D, particules, BSP arbres, et ainsi de suite). Y a-t-il des bons exemples là-bas qui embrasse vraiment la conception axée sur les données et montre comment ce travail pourrait, dans la pratique? Je peux labourer à travers de grandes bases de code si nécessaire.

Ce que je suis particulièrement intéressé par le mantra est « là où il y a un il y a beaucoup », que je ne peux pas vraiment l'air de se connecter avec le reste ici. Oui, il y a toujours plus d'un ennemi, mais, vous avez encore besoin de mettre à jour chaque ennemi individuellement, parce qu'ils ne bougent pas de la même façon maintenant ils sont? Idem pour le « balls'-exemple dans la réponse acceptée à la question ci-dessus (en fait, je demandais cela dans un commentaire à cette réponse, mais n'ont pas encore obtenu une réponse). Est-ce simplement que le rendu aura besoin que les positions, et non pas les vitesses, alors que la simulation de jeu aura besoin à la fois, mais pas les matériaux? Ou suis-je manque quelque chose? Peut-être que je l'ai déjà compris et il est un concept beaucoup plus simple que ce que je pensais.

Les pointeurs serait très apprécié!

Était-ce utile?

La solution

Alors, quel est DOD tout au sujet? De toute évidence, il est sur la performance, mais pas seulement cela. Il est également sur le code bien conçu qui est lisible, facile à comprendre et même réutilisable. Maintenant objet la conception orientée est tout au sujet de la conception code et les données pour entrer dans « objets » virtuels encapsulées. Chaque objet est une entité séparée avec les variables pour les propriétés de cet objet pourrait avoir et des méthodes pour agir sur elle-même ou d'autres objets dans le monde. L'avantage de la conception orientée objet est qu'il est facile de modéliser mentalement votre code en objets parce que le monde entier (réel) autour de nous semble fonctionner de la même manière. Les objets ayant des propriétés qui peuvent interagir les uns avec les autres.

Maintenant, le problème est que le cpu dans votre ordinateur fonctionne d'une manière complètement différente. Il fonctionne mieux lorsque vous laissez faire les mêmes choses encore et encore. Pourquoi donc? En raison d'une petite chose appelée cache. Accès à la RAM sur un ordinateur moderne peut prendre 100 ou 200 cycles CPU (et la CPU doit attendre tout ce temps!), Ce qui est beaucoup trop long. Donc, il y a cette petite partie de la mémoire sur le processeur qui est accessible très rapidement, la mémoire cache. Le problème est qu'il est seulement quelques sommets de MB. Donc, chaque fois que vous avez besoin de données qui n'était pas dans le cache, vous avez encore besoin d'aller le long chemin vers la RAM. Ce n'est pas seulement de cette façon pour les données, la même chose pour le code. Essayer d'exécuter une fonction qui est pas dans le cache d'instructions entraînera un décrochage alors que le code est chargé de la RAM.

Retour à la programmation orientée objet. Les objets sont grandes, mais la plupart des fonctions ont besoin seulement une petite partie de ces données, donc nous cache débilitante en chargeant les données inutiles. Les méthodes appellent d'autres méthodes qui appellent d'autres méthodes, Thrashing votre cache d'instructions. Pourtant, nous faisons souvent beaucoup de la même chose encore et encore. Prenons une balle d'un jeu par exemple. Dans une mise en œuvre naïve chaque balle pourrait être un objet distinct. Il pourrait y avoir une classe de gestionnaire de balle. Il appelle la fonction de mise à jour de la première balle. Il met à jour la position 3D en utilisant la direction / vitesse. Cela provoque beaucoup d'autres données de l'objet à charger dans le cache. Ensuite, nous appelons la classe mondiale Manager pour vérifier une collision avec d'autres objets. Cela charge beaucoup d'autres choses dans le cache, peut-être qu'il provoque même le code de la classe gestionnaire de balle d'origine pour obtenir chuté de cache d'instructions. Maintenant, nous revenons à la mise à jour de la balle, il n'y avait pas de collision, alors nous revenons au gestionnaire de balle. Il pourrait avoir besoin de charger un code nouveau. Prochaine étape, puce n ° 2 mise à jour. Cela charge beaucoup de données dans le cache, monde des appels ... etc Donc, dans cette situation hypthetical, nous avons 2 stands pour le code de chargement et supposons que 2 stands pour le chargement des données. C'est d'au moins 400 cycles gaspillés, pour 1 balle, et nous n'avons pas pris les balles qui ont frappé quelque chose d'autre en compte. Maintenant, un court CPU à partir de 3 GHz afin que nous ne vont pas à l'avis d'une balle, mais si nous avons 100 balles? Ou encore plus?

Donc, c'est le là où il y a une histoire, il y a beaucoup. Oui, il y a des cas où vous avez seulement sur l'objet, vos classes de gestionnaire, l'accès aux fichiers, etc. Mais le plus souvent, il y a beaucoup de cas similaires. objet Naïf, ou même pas naïfs conception orientée conduira à beaucoup de problèmes. Donc, entrer des données de conception orientée. La clé du DOD est de modéliser votre code autour de vos données, et non l'inverse comme avec OO-design. Cela commence dès les premiers stades de la conception. Vous ne pas d'abord concevoir votre code OO et l'optimiser. Vous commencez par la liste et l'examen de vos données et de penser à la façon dont vous voulez modifier (je vais à un exemple pratique dans un instant). Une fois que vous savez comment votre code va modifier les données que vous pouvez poser d'une manière qui le rend aussi efficace que possible de traiter. Maintenant, vous pouvez penser que cela ne peut conduire qu'à une soupe horrible de code et de données partout mais c'est le cas que si vous le design mal (mauvaise conception est tout aussi facile avec la programmation orientée objet). Si vous concevez bien, le code et les données peuvent être soigneusement conçues autour functio spécifiquesnalité, conduisant à très lisible et même code très réutilisable.

Revenons donc à nos balles. Au lieu de créer une classe pour chaque balle, nous ne gardons que le gestionnaire de balle. Chaque puce a une position et une vitesse. La position de chaque balle doit être mis à jour. Chaque balle doit avoir un contrôle de collision et toutes les balles qui ont frappé besoin de quelque chose à prendre des mesures en conséquence. Donc, juste en prenant un coup d'œil à cette description que je peux concevoir tout ce système de manière beaucoup mieux. Mettons les positions de toutes les balles dans un tableau / vecteur. Mettons la vitesse de toutes les balles dans un tableau / vecteur. Maintenant, nous allons commencer par ces deux itérer allong tableaux et mettre à jour chaque valeur de position avec elle est la vitesse correspondante. Maintenant, toutes les données chargées dans le cache de données sont des données que nous allons utiliser. Nous pouvons même mettre une commande pré-chargement intelligent pour déjà pré-charger des données de tableau à l'avance afin que les données dans le cache pour quand nous y accéder. Ensuite, contrôle de collision. Je ne vais pas entrer dans les détails ici, mais vous pouvez imaginer à quel point la mise à jour toutes les balles après l'autre aide peut. Notez également que s'il y a une collision, on ne va pas appeler une nouvelle fonction ou quoi que ce soit. Nous gardons juste un vecteur avec toutes les balles qui ont eu collision et lorsque la vérification de collision est fait, nous pouvons mettre à jour tous les uns après les autres. Voyez comment nous venons de beaucoup d'accès à la mémoire de presque aucun en posant nos données différemment? Avez-vous aussi un avis comment notre code et les données, même si ne sont pas conçus de manière OO plus, sont encore faciles à comprendre et facile à réutiliser?

Donc, pour revenir à la « où il y a une il y a beaucoup ». Lors de la conception code OO vous pensez un objet, le prototype / classe. Une balle a une vitesse, une balle a une position, une balle se déplace chaque image par la vitesse de lui, une balle peut frapper quelque chose, etc. Quand vous pensez à ce sujet, la position, vous penserez à une classe, avec une vitesse et une la fonction de mise à jour qui déplace la balle et le contrôle de collision. Toutefois, lorsque vous avez plusieurs objets dont vous avez besoin de penser à tous. Les balles ont des positions, la vitesse. Certaines balles peuvent avoir une collision. Voyez-vous comment nous ne pensons pas à un objet individuel plus longtemps? Nous pensons à tous et nous concevons le code beaucoup différemment maintenant.

J'espère que cette aide à répondre à votre deuxième partie de la question. Ce n'est pas de savoir si vous devez mettre à jour chaque ennemi ou non, il est à peu près la façon la plus efficace de les mettre à jour. Et lors de la conception que vos ennemis à l'aide DOD ne peuvent pas gain de performances beaucoup d'aide, la conception de l'ensemble du jeu autour de ces principes (uniquement le cas échéant!) Peut conduire à beaucoup de gains de performance!

sur la première partie de la question, qui est d'autres exemples de DOD. Je suis désolé mais je n'ai pas beaucoup là-bas. Il y a un très bon exemple bien, je suis tombé sur ce il y a quelque temps, une série de données axées sur la conception d'un arbre de comportement par Bjoern Knafla:

Autres conseils

Je lis la question que vous et lié à l'article.

J'ai lu un livre sur le sujet des données Driven Design.

Je suis à peu près dans le même bateau que vous.

La façon dont je comprends l'article de Noel est que vous concevez votre jeu dans l'objet typique manière orientée. Vous avez des classes et des méthodes de travail sur les classes.

Une fois que vous avez fait votre conception, vous vous posez la question suivante:

Comment puis-je organiser toutes les données que j'ai conçus dans une énorme blob?

Pensez en termes d'écriture de votre conception entière comme une méthode fonctionnelle, avec beaucoup de méthodes subordonnées. Cela me rappelle les programmes Cobol 500000 ligne massive de ma jeunesse.

Maintenant, vous ne serez probablement pas écrire tout le jeu comme une énorme méthode fonctionnelle. Vraiment, dans l'article, Noel parle de la partie de rendu d'un jeu. Pensez-y comme un moteur de jeu (une énorme méthode fonctionnelle) et le code pour conduire le moteur du jeu (le code POO).

  

Ce que je suis particulièrement intéressé par le mantra est « là où il y a un il y a beaucoup », que je ne peux pas vraiment l'air de se connecter avec le reste ici. Oui, il y a toujours plus d'un ennemi, encore, vous avez encore besoin de mettre à jour chaque ennemi individuellement, parce qu'ils ne bougent pas de la même façon maintenant ils sont?

Vous pensez en termes d'objets. Essayez de penser en termes de fonctionnalité.

Chaque mise à jour de l'ennemi est une itération d'une boucle.

Ce qui est important est que les données de l'ennemi est structuré de façon à être dans un emplacement de mémoire, plutôt que répartis sur instanciations objet ennemi.

scroll top