onLevelLoaded not being called
by Arden · in Torque Game Builder · 08/24/2010 (9:21 pm) · 24 replies
Hiya all,
I have two functions in separate CS files:
Archer_Tower.cs:
I have two functions in separate CS files:
Archer_Tower.cs:
function A::onLevelLoaded(%this, %scenegraph)
{
echo("A::onLevelLoaded called");
}Zombie_Spawner.cd:function B::onLevelLoaded(%this, %scenegraph)
{
echo("B::onLevelLoaded called");
}When I run the game, I only get an echo statement for function B. Both cs files are exectuted in the game.cs here, prior to loading the level:exec("./Archer_Tower.cs");
exec("./Zombiespawner.cs");Any ideas on what I might be doing wrong?
#2
08/24/2010 (11:43 pm)
I removed the underscore to ArcherTower.cs. No change, still doesn't work.
#3
Are you sure that you have an object in your scene with it's class set to "A"?
08/25/2010 (12:40 am)
Sorry, I was on my mobile and thought it was a space, not an underscore.Are you sure that you have an object in your scene with it's class set to "A"?
#4
I think you're just using 'loadLevel' which can load a single level at a given time, which in your example is 'B'. So 'A' does not get loaded and the callback does not occur.
08/25/2010 (4:51 am)
Are you creating two seperate windows and loading the levels into it? I think you're just using 'loadLevel' which can load a single level at a given time, which in your example is 'B'. So 'A' does not get loaded and the callback does not occur.
#5
08/25/2010 (6:49 am)
I'm not sure if this was a typo or not but you named one of your files Zombie_Spawner.cd. If that's not the case, try moving both scripts into the behavior folder so that they automatically load and you don't have to call them from another script. That'll atleast test the onLevelLoaded part.
#6
08/25/2010 (1:02 pm)
@ Patrick: I define the class the class of the object in Datablock.cs:datablock t22SceneObjectDatablock(ArcherTowerDataBlock)
{
class = "ArcherTower";
imageMap = "towerimagemap";
Layer = 0;
//useSourceRect = "0";
//sourceRect = "0 0 1.73091e-039 6.20121e-039";
//canSaveDynamicFields = "1";
size = "8.819 10.556";
CollisionActiveSend = "1";
CollisionActiveReceive = "1";
CollisionPhysicsSend = "0";
CollisionPhysicsReceive = "0";
CollisionPolyList = "-0.253 0.751 0.176 0.751 0.176 0.889 -0.259 0.889";
};
#7
08/25/2010 (1:07 pm)
@Aditya: No, I'm using one single window, and I'm not loading multiple levels. They're just two separate script files. One handles the spawning of the Zombies, and the other handles the spawning of a Tower. I've tested the code of the Tower inside of the Zombie script file and it works. So it's really a matter of trigering the Onlevelloaded function inside of the Zombiespawner.cs.
#8
Here is the actual full function:
By the way, do scripts in the behavior folder need an Onlevelloaded function to be called or can the script be automatically trigerred without a function?
08/25/2010 (1:14 pm)
@Patrick: It was a typo on the post :) I moved the two scripts in the behavior folder, good idea. Same result. The problem really seems to be that the onLevelloaded in the ArcherTower.cs script doesn't get called. Here is the actual full function:
function ArcherTower::onLevelLoaded(%this, %scenegraph)
{
echo("ArcherTower::onLevelLoaded called");
%Tower = new t2dStaticSprite()
{
config = Archer_TowerDataBlock;
scenegraph = %this.scenegraph;
//LinearVelocity = %linearVelocity;
//rotation = 90;
};
%Tower.setPosition(-18,-16);
%this.scan();
}By the way, do scripts in the behavior folder need an Onlevelloaded function to be called or can the script be automatically trigerred without a function?
#9
If you create the object via script then "onLevelLoaded" never gets fired for that object. For objects created in script, use the "onAdd" event instead:
function ArcherTower::onAdd(%this)
If that is indeed your problem you'll also have to change this line:
scenegraph = %this.scenegraph;
to this:
08/25/2010 (1:48 pm)
This may be a timing issue. Does the ArcherTower object exist in the level editor before the script is executed?If you create the object via script then "onLevelLoaded" never gets fired for that object. For objects created in script, use the "onAdd" event instead:
function ArcherTower::onAdd(%this)
If that is indeed your problem you'll also have to change this line:
scenegraph = %this.scenegraph;
to this:
scenegraph = $myLevel; //or whatever name given to your scenegraph
#10
I've tried using onAdd, still doesn't trigger.
And thanks, appreciate everyone's help. Getting a bit annoyed with this one :)
Also, I'd be interested to know how you would go about achieving the same result. My intent is really to handle much of the object creation through code, as it fits more with the type of game. A level gets loaded, and the basic objects are created through code.
Here are the steps I'm taking for t2dStaticSprites:
1) Declare the object in its datablock.
2) Create it throught the onlevelloaded function with new t2dStaticSprite.
Here are the steps I'm taking for t2dAnimatedSprites:
1) Declare the object in its datablock.
2) Create it through various functions in the game with new t2dAnimatedSprite.
I also use onAddToScene to set various properties after these steps, such as setting animations and variables.
Is there anything I'm missing?
Also, can you tell me the difference between onAdd and onAddtoscene?
08/25/2010 (2:02 pm)
Kevin, it's entirely created through a Datablock and the onLevelloaded function. The actual above function is the one creating the Tower. This function works if I place it in another CS file. It just doesn't trigger in it's own CS file. I've tried using onAdd, still doesn't trigger.
And thanks, appreciate everyone's help. Getting a bit annoyed with this one :)
Also, I'd be interested to know how you would go about achieving the same result. My intent is really to handle much of the object creation through code, as it fits more with the type of game. A level gets loaded, and the basic objects are created through code.
Here are the steps I'm taking for t2dStaticSprites:
1) Declare the object in its datablock.
2) Create it throught the onlevelloaded function with new t2dStaticSprite.
Here are the steps I'm taking for t2dAnimatedSprites:
1) Declare the object in its datablock.
2) Create it through various functions in the game with new t2dAnimatedSprite.
I also use onAddToScene to set various properties after these steps, such as setting animations and variables.
Is there anything I'm missing?
Also, can you tell me the difference between onAdd and onAddtoscene?
#11
I believe onAdd gets called before onAddtoScene. I always use onAdd.
08/25/2010 (2:09 pm)
It looks like you're trying to create the object from within a callback of that object before it exists. That will never work. Try this:function myLevel::onLevelLoaded(%this)
{
$myLevel=%this;//I assume you still have this
%this.createTower();
}
function myLevel::createTower(%this)
{
echo("myLevel::createTower");
%Tower = new t2dStaticSprite()
{
config = Archer_TowerDataBlock;
scenegraph = %this;
//LinearVelocity = %linearVelocity;
//rotation = 90;
};
%Tower.setPosition(-18,-16);
%Tower.scan();
}I believe onAdd gets called before onAddtoScene. I always use onAdd.
#12
08/25/2010 (2:23 pm)
A slight clarification in your understanding of datablocks: Datablocks are a shortcut/convenience to apply identical parameters to multiple objects. Its not correct to think you have declared or created anything in the object oriented programming context.%Tower = new t2dStaticSprite()//this is when an object is created
{
config = Archer_TowerDataBlock;//apply preconfigured values to this new object
};
#13
At least now with these changes the object seems the be created. But it doesn't display on screen. Still investigating that part...
Thanks for the clarification on Datablocks!
08/25/2010 (2:28 pm)
Makes more sense to use it there, for now it's been scattered through various cs files and it's getting hard to know what gets created where. I'll do that from now on. At least now with these changes the object seems the be created. But it doesn't display on screen. Still investigating that part...
Thanks for the clarification on Datablocks!
#14
Here is the code from my game.cs file:
I want to keep object creation for the level and actual functionality separate. The challenge I now have is that the function never gets called. Any idea why?
08/25/2010 (3:22 pm)
Actually, I do have one additional question based on this refactoring:Here is the code from my game.cs file:
function myLevel::onLevelLoaded(%this)
{
$myLevel = %this;
echo ("$myLevel=%this");
%this.createTower();
echo ("%this.createTower()");
}
function myLevel::createTower(%this)
{
echo("myLevel::createTower fired");
%Tower = new t2dStaticSprite()
{
config = Towerdatablock; //Class is "Tower"
scenegraph = %this;
};
}And here is the code from my renamed Tower.cs file (executed from game.cs):function Tower::OnAdd(%this, %scenegraph)
{
echo("Tower::OnAdd called");
%Tower.setPosition(-18,-16);
//%this.scan();
}I want to keep object creation for the level and actual functionality separate. The challenge I now have is that the function never gets called. Any idea why?
#15
08/25/2010 (3:58 pm)
NM figured that part out. I just replaced function Tower::OnAdd by function myLevel::createTower(%this). Object is still not appearing though.
#16
Technically, you don't need the datablock. I don't use datablocks in my code, but my understanding is they provide a nice shortcut when configuring objects in the level designer (it saves a lot of time). But if you are like me and create objects via code, you can stop using the datablocks:
08/25/2010 (4:01 pm)
According to your datablock, the class name is "ArcherTower".Technically, you don't need the datablock. I don't use datablocks in my code, but my understanding is they provide a nice shortcut when configuring objects in the level designer (it saves a lot of time). But if you are like me and create objects via code, you can stop using the datablocks:
function myLevel::createTower(%this)
{
echo("myLevel::createTower fired");
%Tower = new t2dStaticSprite()
{
scenegraph = %this;
class = "ArcherTower";
};
}
function ArcherTower::OnAdd(%this)//i don't think the scenegraph gets passed in...
{
echo("Tower::OnAdd called");
%this.imageMap = "towerimagemap";
%this.Layer = 0;
//useSourceRect = "0";
//sourceRect = "0 0 1.73091e-039 6.20121e-039";
//canSaveDynamicFields = "1";
%this.size = "8.819 10.556";
%this.CollisionActiveSend = "1";
%this.CollisionActiveReceive = "1";
%this.CollisionPhysicsSend = "0";
%this.CollisionPhysicsReceive = "0";
%this.CollisionPolyList = "-0.253 0.751 0.176 0.751 0.176 0.889 -0.259 0.889";
%Tower.setPosition(-18,-16);//can you guess why this fails?
}
#17
It's funny though, because it seems that the heart of the problem lies in the way Datablocks are adressed. By attributing the class directly in the createTower function, the On Add is recognised. By using config = Towerdatablock, the class does not get attributed. Really weird.
Hey, thanks again Kevin, I've been struggling with this all morning! :))
08/25/2010 (4:37 pm)
Indeed! %Tower is local to a function, so it doesn't exist there. Replaced it with %This and it works :)It's funny though, because it seems that the heart of the problem lies in the way Datablocks are adressed. By attributing the class directly in the createTower function, the On Add is recognised. By using config = Towerdatablock, the class does not get attributed. Really weird.
Hey, thanks again Kevin, I've been struggling with this all morning! :))
#18
08/25/2010 (5:21 pm)
When I see a developer such as yourself working on a problem all morning by searching the forums and doing his due diligence, I want to help.
#19
08/25/2010 (5:28 pm)
Well, it makes a BIG difference. So thank you for your many posts in helping me. You've just earned a special thanks section in the game ;)
#20
08/25/2010 (5:31 pm)
Cool!
Torque Owner RollerJesus
Dream. Build. Repeat.