How to find my game objects

Oct 8, 2011 at 10:31 AM

OK, so I have a scene and I've got it nicely set up with terrain, lights and a camera. I've also added to it a teapot and a textured smoothed cube. All fine so far. Now I want to add some game logic.

How do I find the cube and the teapot so I can fire the cube at the teapot?

How do I check whether the cube collides with the terrain or the teapot?

How do I destroy and/or clone the cube, so I can fire another and another?

If the answer is to create objects in code and add them to the scene, how do I do that?

Any clues much appreciated.

Oct 8, 2011 at 10:54 AM
- Name the cube and than use Scene.Find(name) to get it.
- Unfortunately we don't have a dedicated collision system yet. You can do a rough check of their bounding boxes, models will always have a bounding box. If your cube is small enough to be treated as an ammo, you could to a point terrain test using DrawableSurface.IsAbove.
- To destroy something, use Scene.Remove
- To create an object in code, just use new DrawableModel(...) and Scene.Add()
- Cloning an object from xml(or xaml) is a bit more complicated, instead of adding the object to the scene, you have to:
1. Create a seperate xml(or xaml) file that describes the object, the root element can be a DrawableModelContent or anything alike.
2. Use the extension method Content.Create(assetName) instead of Content.Load(assetName), this will create a new instance of the object from the content file instead of loading an existing instance.
3. Add the object to the scene using Scene.Add().
Oct 9, 2011 at 10:01 AM

Thanks, that answers most of my questions. I think I understand Content.Create and it should do what I need, although it would be nicer to create it in the scene in situ and clone it as needed. I assume I can rename these objects without breaking anything?


Oct 10, 2011 at 5:09 AM
Yes, you can rename them.
Oct 18, 2011 at 10:21 AM

OK, I tried that with mixed results. First, I tried this.

      var tile_scene = Content.Create<DisplayObject>("Tile_scene");

This does not work, nor will it. The code tries to obtain and invoke a MethodInfo for ContentManager.ReadAsset but this is a generic method. You can't invoke it this way, and it triggers an InvalidOperationException, as expected. So next I tried this.


      var cf = new ContentFactory(Content);
      var tile_scene = cf.Create<DisplayObject>("Tile_scene");

This works just fine, but I'm not sure this is what I want. I'm looking for a lot of instances of the same object, identical appearance, but in different positions. So I tried this.

      var tile = tile_scene.Find<DrawableModel>("tile");
      var tile2 = new DrawableModel(tile.Model, tile.Material);

In other words I created a clone of the object using the same underlying model and material. This works just fine. Is there some reason I shouldn't be doing this?

Finally, I created 100 of these objects in a grid format and ran into performance problems. The frame rate is down to 40 and CPU usage is 100% on one CPU (quad-core), while the GPU is running 7% (ATI 4770). I haven't yet tried to find out what is causing it, but the heavy CPU usage is a major concern.



Oct 18, 2011 at 12:09 PM
The reflection invoke of ReadAsset method might be a bug. I'll look into it. (If you are using it on Windows Phone, if will fail, and the ContentFactory is intended to be used on Windows Phone in that case)
What you're doing is manually cloning model, I think it is not a problem.

The performance problem is a big issue, I've been focusing most of my attentions on functionality beforehand, it seems I'm going to have a tough time tuning performance :-(
Oct 19, 2011 at 10:08 AM

My apologies -- I had forgotten how expensive SpriteBatch is. My debugging hud was chewing up most of the performance. With that switched off the limit is around 800 textured tiles before the frame rate drops off. At this point CPU is 100% on one core and GPU is <5%. There is some culling going on, because the CPU drops to ~60% if all the objects are off screen.

I ran a profile, and there is nothing in your code using any cycles. The main functions consuming CPU are EffectPass.Apply() and BasicEffect.get_texure() in Xna.Framework. If I read that correctly, the only strategy that is going to help is some kind of batching or caching to cut down on calls to XNA. I think that in cases where a lot of models share one material you can gain benefit from combining them into a batch.