I've been through many forum pages, from yoyogames to gmc, and I gathered up the most information I can on how to speed up your 3D games. And I came up with *23* tips on how to make your game run faster in 3D. It's an information I gathered from different forum pages, plus a couple from me. These tips really helped me make my 3D games run faster and I'm sure it will help you guys too. If you guys have any tips that are not included in here, please do post them here. This is for sharing others some good information that will help us during the making of 3D games.
Don't argue if any of the information is wrong; just give a clear explanation. Any feedbacks will also do.
Tip one: Turn Culling On
By setting the culling to true, only one side of every polygon is drawn.
Less drawn stuffs means more speed. Here it is:
Create Event:
d3d_set_culling(true)Tip two: Define all drawing actions only once.
Draw event is like step event only it is useful for drawing actions since it only reads thru your code every time something is drawn into the game (by system or literally drawn into the game). This causes to define the arguments, and other functions, as many times. You need to control this by defining them to draw once; mostly texture.
Create Event:
x1=x-8 y1=y z1=0 x2=x+8 y2=y z2=16 tex[0] = background_get_texture(texture)Draw Event:
d3d_draw_wall(x1,y1,z1,x2,y2,z2,tex[0],1,1);
Tip three: Define models only once
As the same way with textures, you are defining the models only once per object. To do this, you use d3d_model functions since it causes much faster speed to your game than regular d3d_draw functions.
Create event:
global.models[0] = d3d_model_create(); global.models[1] = d3d_model_create(); d3d_model_block(global.model[0],x,y,0,x+8,y+8,8,1,1) d3d_model_block(global.model[1],x,y,9,x+32,y+32,1,1)Then when you want to draw a model just refer to the global variables that store your models like this:
Draw event:
d3d_model_draw (global.model[0],0,0,0,texture);If you are loading an imported model in the middle of the game (there are some cases where the game may need the models to load while playing) make sure to create it once AND make sure the object that is drawing it is invisible at first. Then little by little you draw one by one, each object of the same placed in there (depends on distance). This is for avoiding crashes, too.
Tip four: Don't draw objects beyond the cameras view
This is the most common trick and most use as well. This will disable any drawn polygons outside the camera’s view. Of course, when you play a first person shooter, do you expect to see what’s behind you while looking forward at the same time? Well it’s possible but in most 3D games, you are focusing on the main controllable player at its view so you don’t need to draw all objects while you can’t see them. This is a very useful technique:
Draw Event:
if point_distance(x,y,obj_player.x,obj_player.y)>240 exit //Then goes the rest of the drawing actions here.You can also do the same trick but instead of exiting, you ask if the object is beyond the fog view (of course, you can’t see anything beyond the fog.
Create Event:
d3d_set_fog(true,c_black,min_distance,global. max_distance)Draw Event:
if (sqr(x-obj_camera.x)+sqr(y-obj_camera.
y)+sqr(z-obj_camera.z) < sqr(global.max_distance)) then
{
//object drawing code
}Tip five: set your objects invisible when not neededThis little trick I discovered it myself. It seems that when you turn your object invisible, it will disable the draw event and other drawing actions included in the object. This can improve your speed a lot if you’re using a lot of drawing functions in draw event. This option doesn’t work if you are making a model of couple of polygons invisible. The model must have 10-15 or more polygons for this to work. Here’s how it works:
Step event:
visible = point_distance(x,y,obj_player.x,obj_player.y)<240Tip six: Do not redraw the screen of your game for every step.
You know that the screen has to be drawn every step since it has to draw any new changes made per frame at a certain speed. In 3D games, you do have to draw most of the times. You can still control how much does your screen has to be drawn but you need to maintain a balance between the speed of executing an action and the fps. If you use the room speed to adjust the velocity, you can maintain the fps a balance with how many times you draw the screen; depending on how you maintain redrawing the screen. An example, create an object called “obj_redraw” and add the following:
Create event:
alarm[0]=1 set_automatic_draw(false) frame_skip=0 next_second=1 calc_fps=0 fps_readable=0Alarm0 event:
if next_second{
fps_readable=calc_fps
past_time=current_time
fps_steps=0
next_second=0
}
else
fps_steps+=1
if current_time-past_time>1000
next_second=1
if current_time-past_time=0
calc_fps=0
else
calc_fps=fps_steps/(current_time-past_time)
*1000
alarm[0]=1
if calc_fps>0
{
if room_speed/calc_fps>=0 and room_speed/calc_fps+frame_skip<2
{
frame_skip+=room_speed/calc_fps-1
screen_redraw()
}
else
{
frame_skip=room_speed/calc_fps+frame_skip-2
}
}
else screen_redraw()Note: that code doesn't work with GM Studio since the program doesn't need to redraw the game screen.
Tip seven: Keep in balance the amount of polygons in the room
Try to control the amount of polygons when the fps lowers or raises. Of course that lots of polygons won’t really slow down your game but fewer polygons means more optimize will your game be; game will read less vertex points alternately.
You can reduce the amount of polygons in the room when the game lags or when out of distance. Here's a very basic example about a ball drawn simply with model_ellipsoid:
Create Event:
/* This is a very basic example because instead of creating a huge list of drawn vertexes, it is changing from a different model with a different step result.*/ Far=0 sphere[0]=d3d_model_create() d3d_model_ellipsoid(sphere[0],x,y,2,x+8,y+8,10,1,1,35) sphere[1]=d3d_model_create() d3d_model_ellipsoid(sphere[1],x,y,2,x+8,y+8,10,1,1,27) sphere[2]=d3d_model_create() d3d_model_ellipsoid(sphere[2],x,y,2,x+8,y+8,10,1,1,19) sphere[3]=d3d_model_create() d3d_model_ellipsoid(sphere[0],x,y,2,x+8,y+8,10,1,1,10)Draw Event:
far = point_distance(x,y,obj_player.x,obj_player.y)
if far>=50 {
d3d_transform_set_identity()
d3d_model_draw(sphere[0],0,0,0,-1)
d3d_transform_set_identity()}
if far<50 and far>=25{
d3d_transform_set_identity()
d3d_model_draw(sphere[1],0,0,0,-1)
d3d_transform_set_identity()}
if far<25 and far>=15 {
d3d_transform_set_identity()
d3d_model_draw(sphere[2],0,0,0,-1)
d3d_transform_set_identity()}
if far<15 {
d3d_transform_set_identity()
d3d_model_draw(sphere[3],0,0,0,-1)
d3d_transform_set_identity()}
This changes from one model to another every time when the fps changes. You can experiment with this by placing as many models in the room. This is a very hard process but it can come in handy. You can also adjust the amount of polygons depending on how far the model is away from the camera; you don’t need many polygons when the object looks like a small dot from a distance, hehe. This is also another good tip for optimization.For optimization, keep the size of the polygons in balance; this saves up memory. If a polygon is large and haves texture, there may be a chance of lagging there.
Tip eight: Use less objects and variables
This is the most obvious one. If you use too many object, the room will have a hard time reading every single one, especially if it haves to many codes in it; including step event and draw event. Also not to forget that sprites from the objects can slow much down your game so this should be aware too. Try to avoid creating too many objects and sprites; have too much memory; use extensive codes. That way, your game will have a good optimization; this doesn’t speed up your game a lot.
Tip Nine: Draw smaller texture
Textures come with many color pixels but using complex color codes will make the game have a hard time reading it; especially when there are a lot of them. This could waste a lot of memory and slow down, unnoticeably. If you use less color pixels, it’ll be a bit quicker for your game to run so try to avoid large size textures that have many different color codes. Keep in touch with simple colors like using 225 for the color red. You decide either to go for quality or balance. Also if the texture is only a one solid color-covered canvas, then it is better to set the size as 1x1.
Tip Ten: Use parent objects
When you have two or more objects that contain a few events that have the exact similar commands as each other, then why write all those codes on one object and write the same ones again in another object? That’s why there is parent object for. With this, you can write the codes and events in one object and for the rest that uses the same events as this does, you can just place their parent as that object and nothing more. This helps keep a lower amount of memory of your game and split some time creating objects as well.
Tip Eleven: Don’t forget to turn off the background and other stuffs
In 3D, rooms don’t use backgrounds and most of the time background color. So don’t use these if you are not going to need them. Also to include some objects that are none drawing relative (any argument or variables that are functional to any drawing commands and/or drawing events) do not need the visibility on. So for those types of objects, check that out. I doubt this would improve your speed a lot but it is a bit similar as gaining less than 0.5% of memory.
Tip Twelve: Divide one room to certain different rooms
This is for individual objects that have different models each one. When you have too many individual models in one room, the game slows down a bit. I came up with this trick once for my Minecraft imitation game and it worked well although you guys may doubt that this is a good idea. If you have too many individual models in the room, why not divide the room into more different rooms. Sounds very crazy but what I’m trying to explain is that you are going to take out certain amount of objects and place them in a different room but in the same position it was before so that way you have less models in the room.
An easier way to explain this, you duplicate your humongous room filled with lots of models and you are going to delete the first half of your room. Next with the first room, you are going to do the same except it is the other half that you are only going to delete. Now the next part and most complicated, you are going to create an object that detects whether the main player or cam goes outside a specified boundary in the room. If the player crosses that boundary, you change the room to the new one and make sure you set the boundary correctly (that’s the complicated part). Make sure the main player/cam has persistent box checked and other objects that needs to check over the player. It’s very difficult but very handy. Also be aware about the collision checking.
Tip Thirteen: Don’t use lighting
Although lighting is one thing 3D should have, it waste lots of speed in GM 8 (GM 8.1 doesn’t have this problem nor GM Studio). You choose either use lighting or not. You can also deactivate lighting and re-activate it again in a drawing event that doesn’t involve using lighting.
Create event:
d3d_set_lighting(0);
Also shading can reduce a little bit of speed and as well as any interpolation or blending. Try not to us any of these unless you want to go for quality.
Tip Fourteen: Room speed
Well this is not a good idea but it does speed up your game a little bit (sometimes). However, I don’t recommend this since room speed also affects the velocity of how the events are read per step and it doesn’t look good in a lag scene. But if you like, then try to set the room speed to 300 and see if there is any improvements of speed. However, you wouldn’t like it when the player reaches to the edges of the room. Therefore if using room speed, try to create a balance when close to the edges of the room.
Tip Fifteen: Don’t ask the game to check on something many times
Sometime in the Game Maker Program, functions that involve with checking variables, objects, positions, or any other stuffs in the game can really slow down by processing through the resource to find the right result for the checking, not like how C++ runs better without having to face this problem. Examples of this are place_meeting, collision_rectangle, instance_number, etc. But this only happens when it follows by an “if”. However, these are important for game making but try to keep less of these checking actions in your game.
There are also some other functions that just lags your game, especially when using GM HTML5.
Anotheer thing to know about is the difference between “if” and “&&”. It is much faster to use “if” than “&&”. Example:
This is much faster… :
if x>2 {
if x<5 {
if y>=25 {
instance_destroy() }}}… than this one:if x>2 && x<5 && y>=25 { instance_destroy() }Tip Sixteen: Use an appropriate collision checkingCollision checking is very hard for some beginners creating 3D in GML, but it is also something you must be aware when it comes to lagging. When you create a collision script for your 3D game, here are things you must make sure about it:
- Don’t check too much within the game like explained in Tip Fifteen.
- Don’t create a pixel perfect collision script; it means don’t be very precise in collision. Better off check collision in rectangle or circle.
- Allow this to work for parent objects; don’t go placing the script for every collision event with every object.
Using tiles for collision is much better also.
Tip Seventeen: Frame skipping with time line
This may be similar to tip #6 except your doing it with timeline. Create one time line called TimeLine and one object for the frame skipping. Note that the following code doesn't work for GM Studio.
TimeLine: Step 10
screen_redraw()timeline_position=10-global.frameskip
Create Event:
timeline_index=TimeLine timeline_position=10 timeline_running=falseglobal.frameskip=2//this sets the speed level or frame skipping
Step Event:
set_automatic_draw(false) timeline_running=true
Tip Eighteen: Avoid extensive Step Events
Since step events are continued many times, your game is slowing down due to the cause of many char, strings, and other of these are being read many times at every same second. Try to avoid creating very extensive step events or at least use step events. A great trick would be executing the step event codes instead in alarm event and by this you can determine how long it takes to re-execute the code again:
Create Event:
Alarm[0]=3Alarm[0] Event:
//Add your step event codes here
Alarm[0]=3You can adjust the value to any number but the higher the value is will cause the code to be executed in a longer time lapse.
Tip Nineteen: Use GM8.1 for better optimization
The 3D compatibility in GM8.1 (from version 8.1.75 to up) has an update were 3D runs much faster. So it's a good idea to make your 3D games with that version. However, the price isn’t good. You should consider this option if the game you are working on is worth to spend your cash for improvements. If you wasted your money an update to a glitch-like Game Maker with better optimization for a 3D game that is crappy, that’s your problem. Also to point out that Game Maker: Studio is much faster than GM: 8.1 but its cost is much more than GM 8.1. It’s better to have GM: Studio Standard for the necessary needs of making a basic 3D game. However, Most of my tips aren’t compatible with GM: Studio comparing to GM: 8.1 and earlier versions before that. Like I said, it’s up to you to decide.
Tip Twelve: Externally load your resources.
It is better to not save graphics (especially textures) and sounds into the game, because having them within the game means the game will release the sources at loading time and imagine all the memory it will gather, too. It is mostly preferred to have them in a folder WITH the .exe, and have the .exe load them. That way, there will be less loading time at game start and less memory, for a more optimized game. Here is an excellent 3D sound script made by me that executes the sound from the same directory as the exe file. Plus, this script will allow to play the sound from multiply objects; even the same one.
Create Event :
//d3d_sound_create(filename,min,max)
{
snd=sound_add(argument0,2,0)
sound_3d_set_sound_distance(snd,argument1,argument2);
sound_3d_set_sound_position(snd,global.camx-x,z,global.camy-y);
}End Step Event ://This goes to cam object only
{
global.camx = x;
global.camy = y;
}SpaceBar Keyboard Press Event ://d3d_sound_play(loop)
loop=argument0
if loop==true{
sound_play(snd)
sound_loop(snd)}
if loop==false{
sound_play(snd)}
Tip Twenty-One: Use the right primitives (Strips and List) When creating a model using primitive drawing functions, you must use the right type of primitive to draw your model otherwise there is a probability that you are drawing more polygons than usually are drawing. Now there is a thing between strip and list, one is to make separate polygons and the other creates a chain of polygons connected. Which you think is faster? Well it doesn’t matter because it depends on what you are making. The thing is that strips work in a way that it follows all the points, connecting the dots, which uses less code but at some point there are difficult models we need to create that using strips won’t do. That’s why we use list for that. But the truth is that Strips are faster since it is following less drawing functions than the other. But it is not the same with others beside list. Take pr_trianglefan for example. This draws with less drawing functions as so as pr_trianglestrip. The only thing is that it will draw into a fan shape chain, which is good for making ellipsoids or some sort. Each primitive type has its main purpose. Observe the image below.

Notice that fans are created to make a fan shaped chain. As for the strips and list, one uses less vertex points than the other to create a group of polygons. And so there is nothing faster than the other, just techniques to go through.
Tip Twenty-Two: Clean up your Memory
A quote from @Kaleb702:
If you are using Standard, get CleanMem.dll. It's a DLL that 'cleans up' Game Maker's memory usage, making it uses less memory, therefore making it faster.
Tip Twenty-Three: Using dlls to make 3D
Game Maker's 3D isn't that efficient when it comes to processing. However, there are some dlls that allows you to create 3D with better graphics and faster processing in your Game Maker Game. There are GMOgre and Ultimate3D which I know. Sometimes, adapting a new way to make 3D is worth a shot, but you won't be able to use most of my tips here for those.
Well this is all it. Does some of the information helped?
PS: Try checking your fps of your games by drawing a hud on your screen:
Draw Event:
d3d_set_projection_ortho(0,0,80,64)
draw_set_color(c_white) draw_text(32,32,string(fps)) draw_set_color(-1)I dunno, try comparing both fps of your game, with and without these tips.
Download Anti-Lag Document
Good luck in game making!
Edited by MisuMen49, 06 December 2012 - 04:58 PM.



This topic is locked








