Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
Tags

GMLive.gml

Livecoding for GameMaker: Studio / GameMaker Studio 2 · By YellowAfterlife

[Improved in 1.0.59+] Getting a big drop in framerate after updating scripts live

A topic by Fawf_art created Jun 22, 2022 Views: 245 Replies: 6
Viewing posts 1 to 4
(3 edits)

I started getting this problem a couple weeks ago, prior to that everything was working perfectly.

The problem seems to be associated with a particular object, obj_waterfish_vector. When updating the draw script, my frames would drop from 800 to 8. When updating the step event script it goes from 800 to 15. Updating the create event script has no effect.

I did think that I was getting this extreme lag for updating the step and draw of any object. However I think I this might be two separate problems. I say this because I had another object, obj_seaweed, which I was getting a drop of 800 to 35. But this was in a room with 80 or so instances of this object. When there is a single instance, the frames would only drop to around 400.

So there seems to be a particular problem with obj_waterfish_vector.  This is the draw script.

if (live_call()) return live_result;
if initialized==1{
    draw_set_color(c_red);
    draw_set_alpha(0.3);
    #region draw line
    var i,ii,l_size,x1,y1,x2,y2;
    l_size = ds_list_size(ds_path_list)/2;
    x1 = x;
    y1 = y;
    for(i=l_size-1;i>0;i--){
        x2 = ds_path_list[|i*2];
        y2 = ds_path_list[|(i*2)+1];
        draw_line(x1,y1,x2,y2);
        x1 = x2;
        y1 = y2;
    }
    #endregion
    #region draw base mesh
    draw_set_alpha(1);
    var xx,yy,xx2,yy2;
    xx = x;
    yy = y;
    /*
    for(i=0;i<33;i++){
        xx2 = ds_anim_mesh[# 0,i];
        yy2 = ds_anim_mesh[# 1,i];
        draw_set_color(c_blue);
        draw_set_alpha(0.3);
        draw_line(xx,yy,xx2,yy2);
        draw_set_color(c_white);
        draw_set_alpha(1);
        draw_text(xx2,yy2,i);
        xx = xx2;
        yy = yy2;
    }*/
    draw_set_alpha(0.5);
    for(i=0;i<30;i++){
        var p1 = triangles[# 0,i];
        var p2 = triangles[# 1,i];
        var p3 = triangles[# 2,i];
        var x1 = ds_anim_mesh[# 0,p1];
        var y1 = ds_anim_mesh[# 1,p1];
        var x2 = ds_anim_mesh[# 0,p2];
        var y2 = ds_anim_mesh[# 1,p2];
        var x3 = ds_anim_mesh[# 0,p3];
        var y3 = ds_anim_mesh[# 1,p3];
        draw_triangle(x1,y1,x2,y2,x3,y3,0);//29
        }
    draw_set_alpha(1);
    draw_set_color(c_white);
    #endregion
}

And here's the step event

if (live_call()) return live_result;
if initialized == 0
    exit;
var i,xx,yy;
#region calculate anim mesh
for(i=0;i<33;i++){
    var a = 0;// angle
    var spine_i = clamp(round((1-ds_base_mesh[# 0,i])*ds_path_max_points-1),0,ds_path_max_points-1)*2;
    var s_x = ds_path_list[|spine_i+0];
    var s_y = ds_path_list[|spine_i+1];
    var ps_x = ds_path_list[|spine_i-2];            // prev spine x
    var ps_y = ds_path_list[|spine_i-1];            // prev spin y
    var b_x = 0;                    // base x
    var b_y = ds_base_mesh[# 1,i]*fish_width;    // base y
    if is_undefined(s_x)==0 && is_undefined(s_y)==0{
        xx = s_x;
        yy = s_y;
        var r_b_x = 1;
        var    r_b_y = 1;
        if is_undefined(ps_x)==0 && is_undefined(ps_y)==0{
            a = -degtorad(point_direction(ps_x,ps_y,s_x,s_y));    // find angle of spine
            r_b_x = (b_x*cos(a))+(b_y*sin(a));                    // rotate base x
            r_b_y = (b_x*sin(a))-(b_y*cos(a));                    // rotate base y
        }
        ds_anim_mesh[# 0,i] = xx+r_b_x;
        ds_anim_mesh[# 1,i] = yy+r_b_y;
    }
}
#endregion
#region movement
var tar_vec_x,tar_vec_y;
target_direction = degtorad(point_direction(x,y,target_x,target_y));
tar_vec_x = cos(target_direction);
tar_vec_y = -sin(target_direction);
dir_vec_x +=tar_vec_x*target_influence;
dir_vec_y +=tar_vec_y*target_influence;
var _ra; // radian angle
dir = point_direction(0,0,dir_vec_x,dir_vec_y)
_ra = degtorad(dir);
dir_vec_x = cos(_ra);
dir_vec_y = -sin(_ra);
//x+=dir_vec_x*move_speed;
//y+=dir_vec_y*move_speed;
x+=dir_vec_x*move_speed;
y+=dir_vec_y*move_speed;
m_i = floor(ds_path_max_points/2);
//mid_x = ds_path_list[|(m_i*2)+0]-(fish_length/2);
//mid_y = ds_path_list[|(m_i*2)+1]-(fish_length/2);
mid_x = ds_path_list[|(m_i*2)+0]
mid_y = ds_path_list[|(m_i*2)+1]
#endregion
#region behavior
if behavior_mode = "patrol"{
    move_speed = patrol_speed;
    if point_distance(x,y,target_x,target_y)<arrived_distance{
        current_ppoint_i++
        if current_ppoint_i>=ppoint_max
            current_ppoint_i = 0;
        //var next_target;
        //next_target = ds_patrol_points[|current_ppoint_i];
        //if instance_exists(next_target){
        target_x = ds_patrol_points[|0+(current_ppoint_i*2)];
        target_y = ds_patrol_points[|1+(current_ppoint_i*2)];
        home_x = target_x;
        home_y = target_y;
            //}
    }
    var x1,y1,x2,y2,x3,y3,_dist,_size;
    _dist = 180;
    _size = 45;
    x1 = x;
    y1 = y;
    x2 = x1+lengthdir_x(_dist,dir+_size);
    y2 = y1+lengthdir_y(_dist,dir+_size);
    x3 = x1+lengthdir_x(_dist,dir-_size);
    y3 = y1+lengthdir_y(_dist,dir-_size);
    if point_in_triangle(obj_bern.x,obj_bern.y,x1,y1,x2,y2,x3,y3){
        behavior_mode = "hunt";
    }
}
if behavior_mode = "hunt"{
    move_speed = pursuit_speed;
    target_x = obj_bern.x;
    target_y = obj_bern.y;
    if point_distance(x,y,target_x,target_y)>disengagement_distance
    or point_distance(x,y,home_x,home_y)>max_home_dist{
        event_user(1);
    }
}
#endregion

As far as I'm aware there's nothing special about these scripts. This object is a duplicate of a similar object with a different, more developed and complex system in the draw event. That object suffers from the same problem.

I'm yet to go through and check all of the past objects that were reasonably complex that use GMLive in the step and draw events, but I will check those out and update the thread.

Awesome extension btw, I've been using it for a little while and it's saved me a huge amount of time.


:update:

Issue seems to be present in all draw and step events. current version IDE v2020.5.1.16 runtime v2022.5.2.13

For-loops love to slow down games when using live code. I’m not sure if it’s because of “var”, or just because how live code is executed.

My solution to make it faster is to put code inside for-loop into separate script and live update only that script, not event where for-loop is.

That's good to know. This object does use a lot of for loops and it has the worst performance. I am seeing this issue even on some object without for loops however. But that lag might be within what's expected.

Thanks for the workaround, and I might experiment with not temporary variables in the for loops and see what happens.

Developer

If you can email me a small project that this code and enough setup to make it work, I can take a look - as something that implements GML in GML itself, GMLive is usually ~10x slower than native code, but I can add special handling for commonly used bits.

Cool! I've emailed you a project with the object in and GMLive set up. I am getting similar results with other objects, but this one is by far the worst. It may be the case that this object is just weird, or uses a lot of for loops or something.


Ty for the help!

Update. Getting the issue even with very simple code. e.g got a drop in fps from 15k to 9.

if (live_call()) return live_result;
var s_clock = (alarm[0]/main_clock)*3.14;
var r1 = r1_max*sin(s_clock);
var r2 = r2_max*sin(s_clock);
draw_set_color(c_white);
draw_rectangle(x-r1,y-r1,x+r1,y+r1,0);
draw_triangle(x-r2,y,x-r1,y-r1,x-r1,y+r1,0);//left triangle
draw_triangle(x-r1,y-r1,x,y-r2,x+r1,y-r1,0);//top triangle
draw_triangle(x+r1,y-r1,x+r2,y,x+r1,y+r1,0);//right triangle
draw_triangle(x-r1,y+r1,x,y+r2,x+r1,y+r1,0);//bottom triangle

Out of curiousity I tried again but removed "var" temporary variables and it had a small effect but not by much, down to around 20 fps.

This is occuring with 16 of these instances on screen.

in fact there’s nothing wrong with having 20 FPS after reload - GMLive is rather for debugging and shouldn’t be used in compiled game, so it will have no impact on final version of game.