Thursday 21 November 2013

Insomnaic Games Engine, Resistance 2 and its A.I.



Insomniac Games

Insomniac Games is game development company well known for their PlayStation franchises, such as Spyro, Ratchet and Clank, and Resistance. My first Insomniac game was Ratchet and Clank: Up Your Arsenal, in fact I wrote this blog while listening the R&C: UYA OST :P. However another Insomniac game I loved was Resistance 2, for its ambitions and scale which it achieved!

The information on this blog comes from the talk on Navigation in Insomniac Engine at GDC 2011, found here. Reddy Sambavaram speaks about the evolution of the AI Navigation from the ps2 to ps3, and in several of Insomniac's games including Resistance: Fall of Man and Resistance 2, Ratchet and Clank Future series, etc. This blog will mainly go over the sections leading to the end of Resistance 2’s AI development and methods of navigation within their games.

A.I. in General

Well-designed/created A.I. is needed for the player to properly have a challenge from non-controlled opponents. They must be created in a way navigate similar to the player, to give them a worthy opponent. At the same time these opponents must not be abuse able, where they'll be found in a strange situation. Remember A.I. stands for artificial intelligence, so as much as try to replicate our though processes, the AI probably won't be perfect.

Old AI- used in R&C deadlocked

In Ratchet and Clank Deadlocked, the last Insomniac game on the PS2, had A.I. reminiscent of the PS2 era. First off all their paths were hand made, and used way volume paths. Simply referring to the picture above, it meant traveling from point A to B using these paths and volumes. Finally this was all navigated using A-star, a common algorithm for AI used even today.

Nav Meshing

A Nav Mesh is simply a mesh which what the AI will use to navigate the level. The mesh will be what the AI looks at when try to get from one point to another. The mesh is either hand created by designers, or created from a special tool. Also the designer can use this to predetermine where the AI can navigate to and where it can’t. The good part about this, is that the mesh can be having fewer triangles than the actual level, allowing for checking, and in the end faster path finding.


Resistance:Fall Of Man

 

When they moved to the PS3, Insomniac used navigation meshes to help with AI for their flagship PS3 game, Resistance: Fall of man. Their work began with a designer who would lay the nav-mesh out in Maya, after which tools would convert them into convex poly meshes for runtime. The polygons were treated as nodes in A* if they shared an edge. However despite the new method, they still ran into an issue, only 8 enemies could navigate the mesh at once. This was due to the “funneling of data”, also known as bottle necking on the PPU (Physics Processing Unit).

Resistance 2 changes 

There were many wanted Change with Resistance 2, however with AI there was 3 major changes. First was the bottle necking issue, which the team looked to PPUs and SPUs to fix. Second was the change of nav mesh, where they wanted to have meshes 9x times the size of the ones in RFOM. Finally there was the challenge of creating AI which would be appropriate for the 8 player coop.  The coop was a fun and frantic mode which I have spent many hours on because of the AI’s successfully implemented. 

Mesh changes 

With the development of Resistance 2 came a good amount of changes in nav meshes and their creation. There were different sizes Nav Meshes in the level now, to deal with the different sizes of enemies, which ranged from the dog sized leapers, to human sized hybrids, and the massive Titans. There were parameterizations for navigation of the mesh so enemies can jump up and down ledges. Polygon shapes created for the nav mesh were not acceptable anymore, so just good old triangles could be laid down. However meshes were clustered together, separated by colors, to allow for the creation of these polygon shapes.



A* or Hierarchical path finding

With the change in meshes, the team debated whether to use the A* algorithm, or a hierarchical path finding. Hierarchical path finding is an organized method which went through all the mesh, first at a high level and then at a lower level. Unfortunately this method had issues when creating a path, as the lower level path wasn’t always created. However at the same time, path caching was introduced, which allowed for efficient checks whether the path can successfully make it to its end point. This method allowed for A* to have a better computation time when finding a path. Also AI would generally just move from one end of room to another, so Hierarchical path finding wasn’t as useful. In the end A* was used, and Hierarchical path finding was scraped for Resistance 2.

Path Corners 

When turning around corners with AI, there is always an issue with the proper path and synchronization. This issue was especially prominent with the new zombie enemies, the Grims, since they ran fast! Fast as in 8 Meters per second, and the IG wanted to keep this speed, despite the problems in syncing the animation and orientation of Grims. To solve this issue, a Bezier curve was implemented to tune the path. The path helped the enemies properly find their way around corner with a nice curve.

Grims

As mentioned earlier Grims were on of the tricky enemies to create, because they would come in huge swarm. With Grims, there were times where up to 50 of them would run through a narrow corridor and about 100 of them in the coop. This would be dangerous to performance since each grim had to see every other grim as an obstacle, while checking for the local environment obstacles.
The team came up with a special method of doing this, called the “Grim cache”. The spark of this idea was that all the Grims shared the same threshold tolerance they had to maintain from the boundaries. The cache would allow every Grim obstacle would look around the boundary edges and cache the closest distance to the boundary for each one. This was similar to their obstacle avoidance method which was used for other AI. In the end seeing dozens of Grims swarming you from every direction became of my highlights of playing Resistance 2.

 In fact because of this I was so impressed with the Grims, the Grim skin became my most favourite Chimera skin to use in competitive multiplayer. :P 

Eliminating the Bottle neck: Using the SPU and PPU

To fix the bottle neck, they moved the processing of the nav-meshes to the PS3’s SPU (Special processing Unit).  To push all the processing on to the SPU, Insomniac batched all the nav queries and ran it full-frame deferred on the PS3’s PPU. All data access was isolated to be pushed to the SPU. A nav SPU job had to be created, which included finding a point on a mesh query, with some restrictions and finding a path between the start and the destination. This is in addition to computing the obstacle processing data for steering behavior.
The SPU processing was split into 3 passes: accumulation, finding nearest boundaries, and flagging tangents. The first accumulated all obstacles in all paths, and the second gathered the nearest boundaries for obstacles. The last pass ran through all the paths, once more looking at all the obstacles and their boundary edge threshold tolerance. This was computed in the previous pass, and it would be used to effectively flag the tangents appropriately. This tangent is used for AI to properly make a path around a corner, and other situations.

Conclusion 

In the end, with all the extreme changes in the AI help Insomniac game achieve their ambitious goal of making Resistance 2. With only a year of full development I was very surprised to see overall quality of the game come out. Despite the overall lack of quality, the MASSIVE scope more than made up for it. In fact Resistance 2 stands as one of my most favourite shooters for being respectable in compromising quality for a scope unseen in most games.  Hopefully this analysis of all their processes put into the AI will inspire someone (or me) to make a game of similar scope one day :D.

Saturday 16 November 2013

MIGS 2013:Umbra 3- How It works



This was from a presentation by Antti Hätälä, from Umbra Software, at MIGS (Montreal International Game Summit) 2013.

Intro

What do many next gen games have in common? Is the improvements over graphics, such as better shaders, higher textures and more polygons being pushed? Well yes, but almost all the next gen games use a powerful software called Umbra 3.

What is Umbra3

Umbra in some languages means shadow, a name similar to its purpose: occlusion culling. Occlusion culling is simply not rendering objects which the player does not see.  
Umbra3 is a middleware for 3D games, which specifically does this. Its true purpose is “powering up” level creation/ rendering saving game developers precious time and resources.

Why use occlusion culling

Using occlusion culling will save on A LOT  of memory, memory which you can use for many things. You can use this memory to stream better detail in the world, such as textures and models. Physics, and AI can have more leeway, allow for more enemies/objects. Most importantly is improved game performance, not just for the higher end PCs, but also for the lower end PCs and consoles.

 

Ways of doing Occlusion Culling Today(Pros and Cons) 

 

1- Use a set amount of geometry to act as a mask occluding the view of the player. This mask is easy for the developers to specify, and provides flexibility. However this can be easily desynchronized from the player’s view, and will result in many artifacts. A case of this would be when the user spins the camera too fast, the occlusion isn’t done fast enough, and/or creates artifacts.
2- Use of algorithms based on what is seen from the user’s perspective to determine what shouldn’t be draw. This doesn’t really on any 3D assets, and all on the code of the programmer. The major issue with this is that is non-automatic and is relies heavily on the CPU.
3- Use the portals and cells method, which involves pre-setting a bunch of rooms aka cells, and window aka portals. Nothing outside cell the user is in will be rendered, but only if the user looks through a portal. The issue with this one is fact this is only good for indoor environments, and cannot be applied to a large field. Also this involves the time consuming process of placing Cells and Portals throughout the finished level.
4- Finally there is the PVS method- (potiental visiblitly set). Basically it involves creating separate software to precompute what objects will be visible from any spot. Once the software is done, it is automatic, and generally artifact free. However the major issue is when you put in a large world, the PVS could take days-weeks to render. In short despite its flexibility in type of level, this method will limit the scale of the level.

How Umbra 3 does it 

 

Using Umbra, was explained to be a 2 step process 

First is the local step of precomputing a visibility map

This is a map of the whole level, which is done ONLY for non-dynamic objects. This map would be generated offline from separate software, and would be fed into the game prior to running it. The reason why this works well is the fact the map, no matter the size, is turned into voxels. This eliminates the issue of having high poly maps, and even large scale ones, while maintaining a good quality.
From here the software constructs the map, using portals and cells, using the following method. 
1- group together empty voxels 
2- Collect all the voxels within cells 
3-Gerate portals between cells   
4- remove portals not contributing to the occlusion 
5- extract the view location. 
After this you have a nice map which will give you the Tome of the Level.

 

Second there is run methods

There are many methods which the software uses at run to improve exsisting methods of Occlusion culling. Breath first traversal is done of the portals rather than recursive, so we don’t waste memory. The occlusion resolution isn’t rasterized, rather portals are rasterized. With this there is a 1-bit visibily maintained per cell when looking through any portal. The rasterized a depth buffer is used to determine the details of any object found in this buffer. This way objects can properly increase and lower in detail with their distance, if wanted from the game developer. Finally because the world is split into cells, you can stream in these blocks that are required for visibility queries.

 

Conclusion

In the end Umbra will reduce run time memory, allowing other processes to be done for the game. These processes can allow for greater emersion in the or even better performance. With this, artist can now put in more levels of detail within the level, while level designers have greater freedom with tool to create better levels. the target frame rates while enabling a new level of artistic freedom and rapid content iteration times for these projects