I'm architecting a component-based game object architecture. In my situation, I have renderables and physics objects. A render scene contains renderables. A physics scene contains physics objects. I have a game object that has a renderable and a physics object. Each of these has absolutely zero coupling. They're even in separate libraries.
One of the more obvious pieces of data a game object needs is position and rotation. Both the renderable and physics object need to read this information and in some cases write to it. What are some efficient approaches to handling information that is specific to a game, not a component, but is needed by some components?
This seems a slightly odd architecture to me - you will be forced to do a lot of work to keep two separate scene graphs synchronised and you'll probably find it impossible to keep them completely decopuled (the situation you are describing in the question is an example, but there will be lots more.....)
I'd encourage you to think about a single game object graph. You can still have physics strategies and render strategies for each object, but I'd suggest seeing them more as "plug-ins" to the game object rather than separate object graphs. This way the game object can have a position / rotation vectors that are accessed by both physics and render components.
An alternative, if you don't fancy re-architecting to a single game object graph, would be to separate out the position / rotation information into a separate structure, e.g. a large array of vectors. Both Physics and Render objects can share access to this structure.
This would imply:
Both Physics and Render objects would need to know the index of their own position in the array (either by storing the index directly, or by some form of hashed lookup)
Both Physics and Render objects would have to be happy with the same position / rotation formats
You'd have to to some extra bookkeeping as objects are created / destroyed
You'd have to be a little careful about concurrency, e.g. what happens if new Physics objects are added while rendering is taking place?
Overall I'm not sure that this gains you much...... but it might make sense if you have some other constraint such as the design of a 3rd-party physics library.
Related
This is probably a basic question with a simple answer, but I just can't seem to wrap my head around the logic behind it.
I will start with a simple example with a well-known Java game, Minecraft. A player is put into a world and is allowed to interact with different objects. Say the player wants wood. He sees a tree, walks over, and cuts it down. He sees another tree, walks over, and does the same. He can do this as many times as he wants, and the game will load in more trees if the player explores far enough. But how is this done? In other words, how can a program make an essentially endless amount of trees that the player will always be able to interact with?
I imagine there is a tree class in the code. But obviously, the programmer has not coded in different class instances, such as tree1, tree2, and so on, since he has no idea how many trees will need to be loaded in the game. So how does the program do this without being told how many trees there will be?
In other words, I do not understand how programs can decide on their own to make x number of class instances instead of the programmer having to manually code his/her own class instances. How do game developers and other programmers do this?
Thank you.
Consider how we might generate a random game map. Let's say the environment of the map will be in a forest. What sorts of objects are part of a forest?
Trees
Critters (i.e. squirrels, rabbits)
Forest floor texture (i.e. grass or fallen leaves)
We start with a basic 100x100 unit game map. We will have the program generate a number of trees between 10 and 30, and also generate the tree's X and Y coordinates with the condition that no tree can have the same X and Y coordinates. We do the same for the other objects.
Now we tell the program to load the game map with all of these objects in place. Done.
Consider a simple grid where each position on the grid can be occupied
by an object. The object could be a tree, rock, or creature.
In this world, I have areas on the map defined as 'growable'.
In these areas, something will grow if there isn't something there already.
The game would have a set of turns. During each turn, I run a routine to
find all the growable spots, and if there isn't something growing there
randomly determine if something should sprout. This way if someone
chops down a tree, that spot can sprout a new tree later in the game.
Perhaps the game is more complex and a simple grid isn't good enough.
Whatever the case, the game has to track all the objects in some way.
I am in a serious need of optimization of my some Unity projects and i have so many objects which are from 3DsMax, so i am wondering if Combining the meshes would have any effect on the memory/performance or i should leave the objects Instance to each other as it would save me some space.
This arise the question that what is the difference between Combined mesh objects or Instance Objects as it will save a lot of memory and hassle if one realy knows the difference and what is better
Looking forward for some Brief information about the two
Thanks
Combining is useful if you have a lot of unique assets that only appear once or twice in a scene, e.g unique buildings in a 3D FPS, but not cloned houses in a SimCity style game. If you have a model that appears many times in a scene it's more performant to have Unity (automatically) batch them, this is Unity's default behaviour. e.g lets say your scene is in an art gallery; if the gallery contains a dozen distinct sculptures then combine them. If it contains a dozen of the same sculpture don't bother, Unity will batch them for you.
However, you should be wary of using different materials, each material adds to the draw count. So, if you had 10 of the same model but using 5 different materials it's going to be expensive. The way round this is to use a texture atlas with a single material, with different UV mapping for each models. This means you have a lot of different models, but save on render time due to the single material.
Also, be aware that transparent shaders much more expensive than opaque, if you have three semi transparent objects in front of each other that's at least 4 render passes.
As you probably know this is a complex subject with a lot of variables (many more than I can describe here) and is best judged by using the profiler.
Here are some general rules of thumb I've learned while creating a game for mobile which naturally is performance critical:
Use as few a materials as possible
Use as fewer textures as possible, share textures between materials
Recycle models as often as possible. Often a model oriented at a different angle or in a different material can look like a whole new model to the player, particularly if their attention is elsewhere in the game
Use LODS extensively
Ensure your models are clean, remove all unnecessary vertices before importing
After importing think if there's anything about the model that could be represented with less vertices
Good use of normal mapping can pay off, depending on the platform. If you can trade in 1000 verts for a 256 px normal map and 50 verts then do it, otherwise dont bother normal mapping just to save a few verts
I created a tutorial that explains draw calls, static batching, lightmapping etc.
https://www.youtube.com/watch?v=x0t2xylbTo8&t=253s
I have a 2D sidescrolling game. Right now, in order to jump, the player must be touching the ground. Therefor, I have a boolean, isOnGround, that is set to YES when the player collides with a tile object, and no when the player jumps. This generates a LOT of calls to didBeginContact method, slowing down the game.
Firstly, how can I optimise this by using one big physics body for the tiles on the floor (for example clustering multiple adjacent tiles into one single physics body)?
Secondly, is this even efficient? Is there a better way to detect if the play is on the ground? My current method opens up a lot of bugs, for example wall jumping. If a player collides with a wall, isOnGround becomes YES and allows the player to jump.
Having didBeginContact called numerous times should in no way slow down your game. If you are having performance issues, I suspect the problem is probably elsewhere. Are you testing on device or simulator?
If you are using the Tiled app to create your game map, you can use the Objects Layer to create a individual objects in your map which your code can translate into physics bodies later on.
Using physics and collisions is probably the easiest way for you to determine your player's state in relation to ground contact. To solve your wall issue, you simply make a wall contact a different category than your ground. This will prevent the isOnGround to be set to YES.
You could use the physics engine to detect when jumping is enabled, (and this is what I used to do in my game). However I too have noticed significant overhead using the physics engine to detect when a unit was on a surface and that is because contact detection in sprite kit for whatever reason is expensive, even when collisions are already enabled. Even the documentation notes:
For best performance, only set bits in the contacts mask for
interactions you are interested in.
So I found a better solution for my game (which has 25+ simultaneous units that all need surface detection). Instead of going through the physics engine, I just did my own surface calculation and cache the result each game update. Something like this:
final class func getSurfaceID(nodePosition: CGPoint) -> SurfaceID {
//Loop through surface rects and see if position is inside.
}
What I ended up doing was handling my own surface detection by checking if the bottom point of my unit was inside any of the surface frames. And if your frames are axis-aligned (your rectangles are not rotated) you can perform even faster checks to see if the point is inside the frame.
This is more work in terms of level design because you will need to build an array of surface frames either dynamically from your tiles or manually place surface frames in your world (this is what I did).
Making this change reduced the cpu time spent on surface detection from over 20% to 0.1%. It also allows me to check if any arbitrary point lies on a surface rather than needing to create a physics body (which is unnecessary overhead). However this solution obviously won't work for you if you need to use contact detection.
Now regarding your point about creating one large physics body from smaller ones. You could group adjacent floor tiles using a container node and recreate a physics body that fits the nodes that are grouped. Depending on how your nodes are grouped and how you recycle tiles this can get complicated. A better solution would be to create large physics bodies that just overlap your tiles. This would reduce the number of total physics bodies, as well as the number of detections. And if used in combination with the surface frames solution you could really reduce your overhead.
I'm not sure how your game is designed and what its requirements are. I'm just giving you some possible solutions I looked at when developing surface detection in my game. If you haven't already you should definitely profile your game in instruments to see if contact detection is indeed the source of your overhead. If you game doesn't have a lot of contacts I doubt that this is where the overhead is coming from.
A colleague and I are talking about how scenes are typically rendered in complex games. He believes the world is rendered recursively in the truest object-oriented fashion, with the world's many actors each overriding a virtual function like Actor.Draw() (e.g. Koopa.Draw(), Goomba.Draw()).
By contrast, I imagined that complex games today would iterate over their scene graph, avoiding virtual function overhead and allowing more flexibility for specialized iterators (e.g. near-to-far vs. far-to-near, skipping certain objects in the tree, etc.) And my experience with OpenGL and DirectX suggested to me that they tend to draw objects in batch, and passing a batch context through a recursive call (i.e. the batch into which a class's Draw() function would draw) seemed like additional parameter-passing overhead that could be avoided with iteration.
Is one method favored over another nowadays? If so, why?
Updating parts of a scene graph might be done recursively. But drawing it is usually done via some spatial partitioning data structure and geometry/render-state batcher in order to prevent overdraw (by drawing front to back), and minimize state switches of the rendering pipeline (batching up data, draw calls that use similar resources and render states). Usually this drawing part is in a way, iterative.
You have to take into account how complex the scenes are, their composition, and how many objects are being drawn. For projects with simpler scenes or where you have certain information beforehand, sequencing your rendering (near-)optimally will not be worth the actual cost of calculating the drawing sequence or batching.
In the end the "favored" method would be project-specific.
I have been reading quite a bit graph data structures lately, as I have intentions of writing my own UML tool. As far as I can see, what I want can be modeled as a simple graph consisting of vertices and edges. Vertices will have a few values, and will so best be represented as objects. Edges does not, as far as I can see, need to be neither directed or weighted, but I do not want to choose an implementation that makes it impossible to include such properties later on.
Being educated in pure object oriented programming, the first things that comes to my mind is representing vertices and edges by classes, like for example:
Class: Vertice
- Array arrayOfEdges;
- String name;
Class: Edge
- Vertice from;
- Vertice to;
This gives me the possibility to later introduce weights, direction, and so on. Now, when I read up on implementing graphs, it seems that this is a very uncommon solution. Earlier questions here on Stack Overflow suggests adjacency lists and adjacency matrices, but being completely new to graphs, I have a hard time understanding why that is better than my approach.
The most important aspects of my application is having the ability to easily calculate which vertice is clicked and moved, and the ability to add and remove vertices and edges between the vertices. Will this be easier to accomplish in one implementation over another?
My language of choice is Objective-C, but I do not believe that this should be of any significance.
Here are the two basic graph types along with their typical implementations:
Dense Graphs:
Adjacency Matrix
Incidence Matrix
Sparse Graphs:
Adjacency List
Incidence List
In the graph framework (closed source, unfortunately) that I've ben writing (>12k loc graph implementations + >5k loc unit tests and still counting) I've been able to implement (Directed/Undirected/Mixed) Hypergraphs, (Directed/Undirected/Mixed) Multigraphs, (Directed/Undirected/Mixed) Ordered Graphs, (Directed/Undirected/Mixed) KPartite Graphs, as well as all kinds of Trees, such as Generic Trees, (A,B)-Trees, KAry-Trees, Full-KAry-Trees, (Trees to come: VP-Trees, KD-Trees, BKTrees, B-Trees, R-Trees, Octrees, …).
And all without a single vertex or edge class. Purely generics. And with little to no redundant implementations**
Oh, and as if this wasn't enough they all exist as mutable, immutable, observable (NSNotification), thread-unsafe and thread-safe versions.
How? Through excessive use of Decorators.
Basically all graphs are mutable, thread-unsafe and not observable. So I use Decorators to add all kinds of flavors to them (resulting in no more than 35 classes, vs. 500+ if implemented without decorators, right now).
While I cannot give any actual code, my graphs are basically implemented via Incidence Lists by use of mainly NSMutableDictionaries and NSMutableSets (and NSMutableArrays for my ordered Trees).
My Undirected Sparse Graph has nothing but these ivars, e.g.:
NSMutableDictionary *vertices;
NSMutableDictionary *edges;
The ivar vertices maps vertices to adjacency maps of vertices to incident edges ({"vertex": {"vertex": "edge"}})
And the ivar edges maps edges to incident vertex pairs ({"edge": {"vertex", "vertex"}}), with Pair being a pair data object holding an edge's head vertex and tail vertex.
Mixed Sparse Graphs would have a slightly different mapping of adjascency/incidence lists and so would Directed Sparse Graphs, but you should get the idea.
A limitation of this implementation is, that both, every vertex and every edge needs to have an object associated with it. And to make things a bit more interesting(sic!) each vertex object needs to be unique, and so does each edge object. This is as dictionaries don't allow duplicate keys. Also, objects need to implement NSCopying. NSValueTransformers or value-encapsulation are a way to sidestep these limitation though (same goes for the memory overhead from dictionary key copying).
While the implementation has its downsides, there's a big benefit: immensive versatility!
There's hardly any type graph that I could think of that's impossible to archieve with what I already have. Instead of building each type of graph with custom built parts you basically go to your box of lego bricks and assemble the graphs just the way you need them.
Some more insight:
Every major graph type has its own Protocol, here are a few:
HypergraphProtocol
MultigraphProtocol [tagging protocol] (allows parallel edges)
GraphProtocol (allows directed & undirected edges)
UndirectedGraphProtocol [tagging protocol] (allows only undirected edges)
DirectedGraphProtocol [tagging protocol] (allows only directed edges)
ForestProtocol (allows sets of disjunct trees)
TreeProtocol (allows trees)
ABTreeProtocol (allows trees of a-b children per vertex)
FullKAryTreeProtocol [tagging protocol] (allows trees of either 0 or k children per vertex)
The protocol nesting implies inharitance (of both protocols, as well as implementations).
If there's anything else you'd like to get some mor insight, feel free to leave a comment.
Ps: To give credit where credit is due: Architecture was highly influenced by the
JUNG Java graph framework (55k+ loc).
Pps: Before choosing this type of implementation I had written a small brother of it with just undirected graphs, that I wanted to expand to also support directed graphs. My implementation was pretty similar to the one you are providing in your question. This is what gave my first (rather naïve) project an abrupt end, back then: Subclassing a set of inter-dependent classes in Objective-C and ensuring type-safety Adding a simple directedness to my graph cause my entire code to break apart. (I didn't even use the solution that I posted back then, as it would have just postponed the pain) Now with the generic implementation I have more than 20 graph flavors implemented, with no hacks at all. It's worth it.
If all you want is drawing a graph and being able to move its nodes on the screen, though, you'd be fine with just implementing a generic graph class that can then later on be extended to specific directedness, if needed.
An adjacency matrix will have a bit more difficulty than your object model in adding and removing vertices (but not edges), since this involves adding and removing rows and columns from a matrix. There are tricks you could use to do this, like keeping empty rows and columns, but it will still be a bit complicated.
When moving a vertex around the screen, the edges will also be moved. This also gives your object model a slight advantage, since it will have a list of connected edges and will not have to search through the matrix.
Both models have an inherent directedness to the edges, so if you want to have undirected edges, then you will have to do additional work either way.
I would say that overall there is not a whole lot of difference. If I were implementing this, I would probably do something similar to what you are doing.
If you're using Objective-C I assume you have access to Core Data which would be probably be a great place to start - I understand you're creating your own graph, the strength of Core Data being that it can do a lot of the checking you're talking about for free if you set up your schema properly