8
« on: November 09, 2018, 05:00:38 pm »
Some things to keep in mind if you're going for 'open world'. I did something similar in a different toolset, but the same things apply.
1. How fast is your camera scrolling / how fast does the player move/how far does the player move in one tick? You have to ask this because it will help you determine how many objects are deactivating/reactivating on any given tick (assuming the player is moving)
2. If you implement camera zooming, be aware that as the camera zooms out, naturally, more objects will be on screen than typical, which can and will impact performance.
3. 'Activation/Deactivatin' isn't..by which I mean, just because something was activated/deactivated, doesn't mean it will be done by the next tick, and bugs with references and collisions may occur because of this
4. Consider adding buffer zones. If the camera moves, and say, an enemy is following you, and interceding obstacles or walls may not stop an enemy before they're deactivated (because the order that intances are processed isn't guarantee). In this case it is best to have two zones, one thats closer to the outer edge of the screen, and one that is further. The furthest is for terrain, and it gets activated/deactivated first, the inner buffer zone gets activated/deactivated *after* the terrain buffer
5. What is your memory budget, if any? What are you aiming for? 2GB, 3GB, 4?
While dynamic activation/deactivation will save you processing, each object thats loaded with a level or scene still takes up memory, and you'd be surprised how fast. Know what you can get away with by stress testing with various variables, datastructures, and dummy objects, and then profile memory usage.
6. If you're planning on loading objects from file at run time, ask how many can be loaded before things slow to a crawl. If you have a fast or modern PC consider going well under any limits you encounter, in order to factor in low-specs. Also, disk read speed will be a factor.
7. Think about the object density on screen with your game. Camera zoom, character movement speed, and world density will all contribute to the limits of activation/deactivation and fileloading/serializing before you start to hit a performance wall. For example, with the resolution I've designed for, and scene sizes, I can afford to put, at most 32 objects in scene (about 0.3 object density per scene), but my scenes are small. This doesn't include actors for eye-candy, such as rain and clouds and UI, which you should add to your instance/actor/object count for safe measure.
8. Know your 'heavy' objects/actors, and your 'light' ones. If you're flush for memory, or designing with higher specs (or don't plan on porting to limited platforms), than you can get away with more. Objects that do very little, you can get away with placing more of them obviously.
9. For stencyl specifically, if you don't need full physics, set every object you can to 'simple physics'
10. Again, for stencyl, always assign an actor to a group, group on group collisions should be cheaper to check for.
11. Events are cheap compared to draw(), always(), and other events that get called every frame or tick. If you can get away with custom events instead of regular events like update, then do so.
12. When all else fails, cut what you don't need. Don't invent new tools or reinvent tools. Instead use the tools you have to the very fullest. An example, early on I made everything an actor, which was a bad move. I realized instead what I could do was use tilemaps as they are intended, and then for lootables, I created an actor with an icon thats only used to identify it in the scene *editor*, a ring with a diamond on it in to indicate 'this is lootable'. This actor was placed on a separate tile layer overlaying the map.
Then I placed this collidable actor over each tile 'container' I wanted the player to be able to loot. During runtime the player wouldn't see these invisible markers used for level design, but if they collided with a container, they'd get rewarded with loot. In the end this was way cheaper than making every single thing an actor just because I wanted *some* of them to be interactive in some way. No matter how big your scenes, you're usually going to benefit from making things tiles instead of full blow objects.
13. Stencyl specific (not necessarily related to open worlds), use the inspector. You can do a LOT of customization for experimentation, in order to get things 'just right'. So if you've already designed a scene or chunks of it, and it turns out you have too much loading/unloading too fast, you could use the inspector panel to tweak and test the players move speed until you find the sweet spot, but thats just one example.
14. Never underestimate the power of swapping things out. In my early builds I created a custom actor for each and every UI iteration. I realized what I could do was create a behavior with an 'actor' attribute. The UI parent actor would control the layout of elements, and the elements would just have events specifically to determine their own state (e.x. hovered, clicked, dragged, etc). This meant if I didn't like the design of something, such as the layout, I could change it with a single swap of an instance or attribute value in the scene editor. This is really just an extension of point 13, but once I realized it it saved me so much trouble.
15. When simulating big worlds, never underestimate the power of simply skipping a loop or two. Using an if-check and a modulo, I had whole sets of objects simulating at half and sometimes a third of my tick rate, and it saved me processing power where I couldn't cut elsewhere. Tricks like this are important when you're dealing with 10k, 20k, 100k+ objects loaded.
Thats all I got for now, but there are people here way more experienced at this. Good thread.