Between the enemies, the buildings, the weapons and the debris, I have a lot of models being created and destroyed all the time in my game.
So I was wondering if I should keep it that way, or if it would be better to recycle them.
I guess it would consist of adding the created models in an array, and kind of deactivate them with a boolean when they are destroyed, instead of calling RemoveModel().
Then, when I need to create a new model, I would cycle through the array and see if any model is deactivated in order to revive it.
And if every model in the array is activated, then I just create a new model and add it to the array.
So, do you guys think it is worth doing that, or is it just a waste of time? Maybe models are already well handled in the background by ZGE?
Recycling models, is it worth it?
Moderator: Moderators
Re: Recycling models, is it worth it?
Hi Ats,
K
If you're experiencing hiccups during gameplay due to models being spawned, recycling models can certainly be a relatively easy remedy. However, if your game already runs completely smooth at the desired framerate on a computer that you consider to be the minimum system requirements, why bother?
K
Re: Recycling models, is it worth it?
It freezes for a few frames on some recent phones when I spawn more than 30 enemies at a time...
So I made a little working example, but I'm not happy with setting the Thing parameters in the general activateThing function. I would prefer them to be set in the model, so I don't have to search everywhere for that bit of code. But I can't seem to find how to simply do that
So I made a little working example, but I'm not happy with setting the Thing parameters in the general activateThing function. I would prefer them to be set in the model, so I don't have to search everywhere for that bit of code. But I can't seem to find how to simply do that
Code: Select all
<?xml version="1.0" encoding="iso-8859-1" ?>
<ZApplication Name="App" Caption="ZGameEditor application" FileVersion="2">
<OnLoaded>
<ZLibrary>
<Source>
<![CDATA[void activateThing(model m)
{
m.Alive = 1;
m.Shape = round(rnd());
m.Position.X = -6;
m.Position.Y = random(0,3);
m.Speed = rnd();
CountAlive ++;
Total ++;
}
void createNewThing()
{
model m = createModel(ThingModel);
SpoolArray.SizeDim1 ++;
SpoolArray[SpoolArray.SizeDim1 - 1] = m;
activateThing(m);
}
void recycleThing()
{
if (SpoolArray.SizeDim1 > 0)
{
// Check for deactivated thing in the spool array
for (int i=0; i<SpoolArray.SizeDim1; i++)
{
model m = SpoolArray[i];
if (!m.Alive)
{
activateThing(m);
return;
}
}
}
// No deactivated thing was found, add a new thing to the spool
createNewThing();
}]]>
</Source>
</ZLibrary>
<ZExpression Expression="SpoolArray.SizeDim1 = 0;"/>
</OnLoaded>
<OnUpdate>
<Timer Name="Spawner" Interval="0.1105">
<OnTimer>
<ZExpression>
<Expression>
<![CDATA[Spawner.CurrentRelativeTime = 0;
Spawner.Interval = rnd()/2;
recycleThing();]]>
</Expression>
</ZExpression>
</OnTimer>
</Timer>
</OnUpdate>
<OnRender>
<RenderText Comment="Alive / Spool" Y="0.9" Scale="0.4" TextExpression="intToStr(CountAlive) + " / " + intToStr(SpoolArray.SizeDim1) + " instead of " + intToStr(Total);"/>
</OnRender>
<Content>
<Mesh Name="SphereMesh">
<Producers>
<MeshSphere Scale="0.2 0.2 0.2" ZSamples="20" RadialSamples="20"/>
</Producers>
</Mesh>
<Mesh Name="BoxMesh">
<Producers>
<MeshBox Scale="0.2 0.2 0.2"/>
</Producers>
</Mesh>
<Model Name="ThingModel">
<Definitions>
<Variable Name="Alive" Type="4"/>
<Variable Name="Shape" Type="4"/>
<Variable Name="Speed"/>
<ZLibrary>
<Source>
<![CDATA[void deactivate()
{
CurrentModel.Alive = 0;
CurrentModel.Position.X = 100;
CountAlive --;
}]]>
</Source>
</ZLibrary>
</Definitions>
<OnUpdate>
<ZExpression>
<Expression>
<![CDATA[if (CurrentModel.Alive)
{
CurrentModel.Position.X += CurrentModel.Speed;
if (CurrentModel.Position.X > 6) deactivate();
}]]>
</Expression>
</ZExpression>
</OnUpdate>
<OnRender>
<ZExpression>
<Expression>
<![CDATA[if (CurrentModel.Alive)
{
if (CurrentModel.Shape) @RenderMesh(Mesh:BoxMesh);
else @RenderMesh(Mesh:SphereMesh);
}]]>
</Expression>
</ZExpression>
</OnRender>
</Model>
<Array Name="SpoolArray" Type="3" SizeDim1="6"/>
<Variable Name="CountAlive" Type="1"/>
<Variable Name="Total" Type="1"/>
</Content>
</ZApplication>
Re: Recycling models, is it worth it?
Hi Ats,
Alternatively you could use a condition that checks a variable from Definitions. Depends a bit on your model whether this makes more sense or not.
K
If you only need to reset a model you can put a CallComponent in Definitions and call that. Here's a simple example ( use left-mouse-button ).Ats wrote: ↑Fri Feb 17, 2023 10:27 amSo I made a little working example, but I'm not happy with setting the Thing parameters in the general activateThing function. I would prefer them to be set in the model, so I don't have to search everywhere for that bit of code. But I can't seem to find how to simply do that
Code: Select all
<?xml version="1.0" encoding="iso-8859-1" ?>
<ZApplication Name="App" Caption="ZGameEditor application" FileVersion="2">
<OnLoaded>
<ZExpression>
<Expression>
<![CDATA[// Spawn 4 boxes
for(int i=0; i<4; i++)
{
BoxArray[i] = createModel(Box);
}]]>
</Expression>
</ZExpression>
</OnLoaded>
<OnUpdate>
<KeyPress Keys="{" RepeatDelay="0.25">
<OnPressed>
<ZExpression>
<Expression>
<![CDATA[// On left click "reset" all boxes by calling BoxResetCall
for(int i=0; i<4; i++)
{
@CallComponent(Component: BoxArray[i].BoxResetCall);
}]]>
</Expression>
</ZExpression>
</OnPressed>
</KeyPress>
</OnUpdate>
<Content>
<Model Name="Box">
<Definitions>
<CallComponent Name="BoxResetCall" Component="BoxReset"/>
</Definitions>
<OnSpawn>
<ZExpression Name="BoxReset">
<Expression>
<![CDATA[//
Box.Position.X = random(0, 8);
Box.Position.Y = random(0, 4);
Box.Rotation.X = random(0, 1);
Box.Rotation.Y = random(0, 1);
//
BoxColor.Color.R = 0;
BoxColor.Color.G = 0;
BoxColor.Color.B = 1;]]>
</Expression>
</ZExpression>
</OnSpawn>
<OnUpdate>
<ZExpression>
<Expression>
<![CDATA[// Animate color
BoxColor.Color.R += App.DeltaTime;]]>
</Expression>
</ZExpression>
</OnUpdate>
<OnRender>
<RenderSetColor Name="BoxColor"/>
<RenderMesh Mesh="BoxMesh"/>
</OnRender>
</Model>
<Mesh Name="BoxMesh">
<Producers>
<MeshBox/>
</Producers>
</Mesh>
<Array Name="BoxArray" Type="3" SizeDim1="4"/>
</Content>
</ZApplication>
Code: Select all
<?xml version="1.0" encoding="iso-8859-1" ?>
<ZApplication Name="App" Caption="ZGameEditor application" FileVersion="2">
<OnLoaded>
<ZExpression>
<Expression>
<![CDATA[// Spawn 4 boxes
for(int i=0; i<4; i++)
{
BoxArray[i] = createModel(Box);
}]]>
</Expression>
</ZExpression>
</OnLoaded>
<OnUpdate>
<KeyPress Keys="{" RepeatDelay="0.25">
<OnPressed>
<ZExpression>
<Expression>
<![CDATA[// On left click "reset" all boxes by setting BoxState to 1 ( reset )
for(int i=0; i<4; i++)
{
BoxArray[i].BoxState = 1;
}]]>
</Expression>
</ZExpression>
</OnPressed>
</KeyPress>
</OnUpdate>
<Content>
<Model Name="Box">
<Definitions>
<Variable Name="BoxState" Type="1"/>
</Definitions>
<OnSpawn>
<ZExpression Name="BoxReset">
<Expression>
<![CDATA[//
Box.Position.X = random(0, 8);
Box.Position.Y = random(0, 4);
Box.Rotation.X = random(0, 1);
Box.Rotation.Y = random(0, 1);
//
BoxColor.Color.R = 0;
BoxColor.Color.G = 0;
BoxColor.Color.B = 1;]]>
</Expression>
</ZExpression>
</OnSpawn>
<OnUpdate>
<Condition Expression="return BoxState;">
<OnTrue>
<CallComponent Component="BoxReset"/>
<ZExpression>
<Expression>
<![CDATA[// Reset is done, set state back to 0
BoxState = 0;]]>
</Expression>
</ZExpression>
</OnTrue>
</Condition>
<ZExpression>
<Expression>
<![CDATA[// Animate color
BoxColor.Color.R += App.DeltaTime;]]>
</Expression>
</ZExpression>
</OnUpdate>
<OnRender>
<RenderSetColor Name="BoxColor"/>
<RenderMesh Mesh="BoxMesh"/>
</OnRender>
</Model>
<Mesh Name="BoxMesh">
<Producers>
<MeshBox/>
</Producers>
</Mesh>
<Array Name="BoxArray" Type="3" SizeDim1="4"/>
</Content>
</ZApplication>
Re: Recycling models, is it worth it?
Thanks Kjell. And with the addition of ModelState, the BoxReset in Box Model can then call substates with their own initialization, which is pretty neat.
But that rise a few questions... As I was merging all my FX into only one Model, I realized that some FX have a different RenderOrder or Category number, in order to display them correctly. Can I simply change those settings in the ModelStates, or will it change all the FX models in game, regardless of their ModelState?
And when I create explosions, a lot of FX Models are created. So I was wondering if, in the end, it is better to create and destroy them, or to have all those unused Models in game with a test on their OnUpdate and OnRender to check if they are alive or not, at each frame... I don't know.
Code: Select all
<OnSpawn>
<ZExpression Name="BoxReset">
<Expression>
switch(CurrentModel.Box_Type) {
case 0: @SetModelState(State:State_Box_Cube); break;
case 1: @SetModelState(State:State_Box_Sphere); break;
}
</Expression>
</ZExpression>
</OnSpawn>
And when I create explosions, a lot of FX Models are created. So I was wondering if, in the end, it is better to create and destroy them, or to have all those unused Models in game with a test on their OnUpdate and OnRender to check if they are alive or not, at each frame... I don't know.
Re: Recycling models, is it worth it?
Hi Ats,
Regardless, a built-in flag mask ( or a couple of booleans ) that let's you enable/disable various events of a model ( Update / Render / Collision ) would have been convenient. Having to wrap everything into conditions gets tiresome quickly
K
Never tried that before, but it seems like changing it on the fly works just fine.Ats wrote: ↑Fri Feb 17, 2023 7:21 pmAs I was merging all my FX into only one Model, I realized that some FX have a different RenderOrder or Category number, in order to display them correctly. Can I simply change those settings in the ModelStates, or will it change all the FX models in game, regardless of their ModelState?
Code: Select all
<?xml version="1.0" encoding="iso-8859-1" ?>
<ZApplication Name="App" Caption="ZGameEditor application" FileVersion="2">
<OnLoaded>
<ZExpression>
<Expression>
<![CDATA[//
for(int i=0; i<16; i++)
{
float a = i*PI/8;
float s = PI*2/3;
SpriteColor.Color.R = sin(a+s*0)*0.5+0.5;
SpriteColor.Color.G = sin(a+s*1)*0.5+0.5;
SpriteColor.Color.B = sin(a+s*2)*0.5+0.5;
Sprite.Position.X = sin(a);
Sprite.Position.Y = cos(a);
Sprite.Position.Z = i;
createModel(Sprite);
}]]>
</Expression>
</ZExpression>
</OnLoaded>
<Content>
<Model Name="Sprite" Position="-0.3827 0.9239 15">
<OnUpdate>
<ZExpression>
<Expression>
<![CDATA[//
Sprite.Position.Z += App.DeltaTime;
if(Sprite.Position.Z >= 16)Sprite.Position.Z -= 16;
Sprite.Category = 15-floor(Sprite.Position.Z);]]>
</Expression>
</ZExpression>
</OnUpdate>
<OnRender>
<UseMaterial Material="SpriteMaterial"/>
<RenderSetColor Name="SpriteColor" Color="0.3087 0.9957 0.1956 1"/>
<RenderSprite/>
</OnRender>
</Model>
<Material Name="SpriteMaterial" Shading="1" Light="0" ZBuffer="0"/>
</Content>
</ZApplication>
Pretty difficult to say what is better without doing benchmarks for your specific situation.Ats wrote: ↑Fri Feb 17, 2023 7:21 pmAnd when I create explosions, a lot of FX Models are created. So I was wondering if, in the end, it is better to create and destroy them, or to have all those unused Models in game with a test on their OnUpdate and OnRender to check if they are alive or not, at each frame... I don't know.
Regardless, a built-in flag mask ( or a couple of booleans ) that let's you enable/disable various events of a model ( Update / Render / Collision ) would have been convenient. Having to wrap everything into conditions gets tiresome quickly
K
Re: Recycling models, is it worth it?
hahaha, another simple yet super explicit and colorful example of yours. Thanks.
For the benchmark, I'll do that when I'll finish fusing all the FX into one Model, now that I know Category can be changed without breaking everything. I'll just have to switch on/off the spool and run some tests.
For the benchmark, I'll do that when I'll finish fusing all the FX into one Model, now that I know Category can be changed without breaking everything. I'll just have to switch on/off the spool and run some tests.
Just like the Disable Component option that only works in preview mode?Regardless, a built-in flag mask ( or a couple of booleans ) that let's you enable/disable various events of a model ( Update / Render / Collision ) would have been convenient. Having to wrap everything into conditions gets tiresome quickly