Asteroid Manager


I have been playing around with porting the asteroid manager to Unity. The code to get this right as per the previous post was very little. I had some issues with the coordinate system, but the guys from the Orthello framework were kind enough to explain things to me.

To get started you need to install the Orthello package from the Unity asset store. Then you drag the OTView object into your scene as follows. The OTView object handles things like the Orthographic camera (needed for 2D) and coordinate systems out the box.

image

The asteroid manager is responsible for managing the asteroids within the game. As per the XNA example we are going to need an asteroid sprite. To create the sprite you drag the Orthello Sprite asset from the project hierarchy onto your scene. Since we want to control the creation and destruction of our sprites through code we will be using an asteroid “prototype” that will serve as a template. To use our new asteroid sprite as a prototype you drag it into the "OT –> Prototypes” folder in the scene hierarchy.

The first thing to do is to disable the asteroid sprite by unchecking the checkbox next to the sprite name as follows:

image

The reason for disabling the prototype is quite subtle. Since we are creating all our asteroid sprite instances based on this prototype we don’t want to accidentally delete to prototype object itself. By disabling the sprite we can safely exclude it from our script processing.

The next thing we want to set is how the sprite behaves in terms of collisions.

image

The depth property specifies the z-position of the object. The collidable property tells unity that the sprite will take part in collision detection. The RigidBody physics setting defines how the sprite should behave in terms of the physics calculations. I am using a Sphere collider type with the collision depth being at the same depth as the sprite and the collision size set to a size within the bounds of the sprite.

The asteroid animation is handled via animation and animation container objects which I will describe below. The properties on the Sprite class for animations are as follows.

image

In the properties above I have indicated that the animation will loop, start playing when the game starts and will start at a random frame. Easy enough and replaces all the code we had in the sprite class for the XNA version.

To define the animation container you need to drag an Orthello SpriteSheet object onto your scene. Orthello supports sprite atlasses for various well known file formats, for now I decided to make use of a simple spritesheet. On the AnimationContainer you just created you need to specify the texture to use, the number of frames and the size of each frame.

image

I specified the Texture by dragging it from the project assets onto the Texture property of the AnimationContainer.

Now that we have defined a container for our animations we need to create an animation for our asteroid sprite. This is done by dragging an Orthello Animation object from the project assets onto our scene. The next step is to define which frame sfrom the AnimationContainer to use for the Animation.

image

Our asteroid animation will make use of one frameset (there is only one in my spritesheet) and will start at frame 0 and end with frame 19. You specify the container by dragging the AnimationContainer you created in the scene onto the container property of the Animation object.

The next step is to create a script for the Asteroid sprite. This script is really basic and all it does is to destroy the asteroid once it moves outside the bounds of the visible area.

// Update is called once per frame
void Update()
{
    if (sprite.outOfView)
    {
        OT.DestroyObject(sprite);
    }
}

The script is attached to the asteroid sprite by dragging it onto the asteroid sprite prototype. When we create our asteroid sprites using the prototype as template the accompanying script will be created automatically.

Finally the AsteroidManager script will be used to create the asteroids and position them randomly on the game screen. I attached the AsteroidManager script to my MainCamera object.

// Update is called once per frame
void Update()
{
    // only go one if Orthello is initialized
    if (!OT.isValid) return;

    // We call the application initialization function from Update() once
    // because we want to be sure that all Orthello objects have been started.
    if (!initialized)
    {
        Initialize();
        return;
    }
    
    // If we have less than 15 objects within Orthello we will create a random asteroid
    if (OT.objectCount <= 15)
        this.SpawnAsteroid();
}

The Update method is responsible for initializing the asteroid manager and to spawn new asteroids if the current object count is less than 15.

// application initialization
void Initialize()
{
    // Create our object pool if we want.
    OT.objectPooling = true;
    if (OT.objectPooling)
        CreateObjectPools();
    
    // set our initialization notifier – we only want to initialize once
    initialized = true;
}

The Initialize method is used to switch on object pooling and to create the object pools.

private void SpawnAsteroid()
{
    // Create a new asteroid sprite based on the Asteroid protoype
    GameObject asteroid = OT.CreateObject("Asteroid");
    if (asteroid != null)
    {
        // activate the game object
        asteroid.gameObject.active = true;
        // get a reference to the animating sprite of the asteroid
        var sprite = asteroid.GetComponent<OTAnimatingSprite>();
        // set the depth
        sprite.depth = 100;
        // the asteroids should not be influenced by gravity
        sprite.rigidbody.useGravity = false;
        // give the sprite a random position and velocity
        this.SetRandomPositionAndVelocity(sprite, OT.view.worldRect);
    }
}

In the above code we create a new GameObject instance based on the “Asteroid” prototype object. We then make sure the gameObject is active and get a reference to the AnimatedSprite object within the gameObject. The sprite is used to set the depth, position and physics settings.

private void SetRandomPositionAndVelocity(OTAnimatingSprite sprite, Rect screenRectangle)
{
    sprite.rotation = Random.value * 360;
    var spawnDirection = (SpawnDirection)Random.Range(0, 3);
    
    switch (spawnDirection)
    {
        
        case SpawnDirection.Left:
            sprite.position = new Vector2(screenRectangle.xMin, (Random.value * Mathf.Abs(screenRectangle.height)) – Mathf.Abs (screenRectangle.yMax));
            sprite.rigidbody.velocity = new Vector3(Random.value * 50, (Random.value * 100) – 50);
            break;
        case SpawnDirection.Top:
            sprite.position = new Vector2((Random.value * Mathf.Abs(screenRectangle.width)) – Mathf.Abs(screenRectangle.xMin), screenRectangle.yMin);
            sprite.rigidbody.velocity = new Vector3((Random.value * 100) – 50, (Random.value * 50) – 50);
            break;
        case SpawnDirection.Right:
            sprite.position = new Vector2(screenRectangle.xMax, (Random.value * Mathf.Abs(screenRectangle.height)) – Mathf.Abs (screenRectangle.yMax));
            sprite.rigidbody.velocity = new Vector3((Random.value * 50) – 50, (Random.value * 100) – 50);
            break;
    }
    
    var normalizedVelocity = sprite.rigidbody.velocity.normalized;
    sprite.rigidbody.velocity = normalizedVelocity * 50;
}

The SetRandomPositionAndVelocity method is very similar to the XNA version in terms of game logic.

The above was all that was required to get the AsteroidManager portion of the game up and running. I am very impressed with the Orthello framework and Unity as a game engine thus far.

Networking is going to have some challenges, but before I get there I am going to have to introduce GUI elements. The reason for this is that I haven’t found a good way to start two instances of unity with “client” and “server’ arguments as per my XNA example. If I can get that working then I won’t need a GUI to allow the user to specify whether the instance is running as server or client.

Advertisements

5 thoughts on “Asteroid Manager

    • Hi

      I’m no expert yet but as I understand it you have two options.

      1. Untick the collidable flag for your object -> no collisions will be handled for this object.
      2. If you need collisions then put the types of objects that should not collide with each other on different collision depths.

      Hope that helps

      • There are some sprites at depth 100 like obstacles and stuff that I want my others sprites to collide with, but I don’t want the other sprites colliding between themselves. So if I set different depths for each sprite they will still keep colliding between themselves because the collision depth must be at least 100 in order to keep the sprites colliding with the bottom borders. Is there a way around this? Thanks

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s