Track builder

This started off as a PC game, but later made it on to Google Play Store!

I decided that I would like to make a game, somewhat similar to a certain racing game involving a certain plumber (please don’t copyright strike me!). I decided to choose Unity, because it has 3D physics and graphics, which I would certainly need.

I started by having a track placing script attached to the camera, and created a wall script which I am quite proud of. The track placer adds all of the placed track to a List, and when a new track is placed, it looks through the list for neighbouring track and decides whether or not to place a wall there. Unfortunately, as you may have guessed, this starts getting really quite laggy when iterating through a huge array of 100 or so pieces. I may have to change it to a HashTable or Dictionary – but I need to research these first.

After this, I made car controls. The car has a trigger collider on the bottom to detect if it is grounded, and thus if it can drive. The turning is less realistic – you don’t have to be moving to turn. I felt that this was a reasonable sacrifice in order to maintain playability and fun.

The scenes between playing and creating transfer data by using a static string. In Unity, static information is preserved between scenes, which is useful. This same string can be used for saving and loading tracks.

After this, I decided to make it a mobile game. This was difficult at first, because it first involved creating a lot of UI which also needed fixed aspect. This means that despite the screen size, the item must stay at the same width to height ratio, which throws nearly everything about screen anchors out of the window. I struggled with this at first, as if the screen had too extreme dimensions, then the buttons would clip offscreen. However, I discovered that Unity has a pivot property in its RectTransforms. This means that you can set where the aspect ratio changes size from, preventing it from clipping off screen if set correctly. Hooray!

However, the next challenge was more difficult. Unity’s buttons only tell you when they are clicked, not if they are down. This means that holding an accelerator would only move you forward once when you let go. I came up with a ‘hacky’ feeling solution for this one, involving borrowed stack overflow code, but it works nonetheless, and that’s good enough. The idea is that you calculate the area of the screen that the button occupies (GetWorldRect) and then check to see if any screen touches are inside that. If you want the code, it is pasted below, although you should strip some things from it as they play in with the rest of the game.

using UnityEngine;

public class IsPressed : MonoBehaviour
{
    public bool down = false;
    public bool oldDown = false;

    public static int totalDown=0;
    public void Start()
    {
        totalDown = 0;
    }
    public static Rect GetWorldRect(RectTransform rt)
    {
        // Convert the rectangle to world corners and grab the top left
        Vector3[] corners = new Vector3[4];
        rt.GetWorldCorners(corners);
        Vector3 topLeft = corners[0];
        Vector2 scale = new Vector2(1,1);
        // Rescale the size appropriately based on the current Canvas scale
        Vector2 scaledSize = new Vector2(scale.x * rt.rect.size.x, scale.y * rt.rect.size.y);

        return new Rect(topLeft, scaledSize);
    }
    private void Update()
    {
        bool changed = false;
        foreach (Touch t in Input.touches)
        {
            if (GetWorldRect(GetComponent<RectTransform>()).Contains(t.position))
            {
                down = true;changed = true;
            }
        }
        if (!changed) down = false;
        if (down && !oldDown) totalDown++;
        if (oldDown && !down) totalDown--;
        oldDown = down;
        totalDown = Mathf.Max(totalDown, 0);
    }

    public bool IsDownRecalc()
    {
        bool changed = false;
        foreach (Touch t in Input.touches)
        {
            if (GetWorldRect(GetComponent<RectTransform>()).Contains(t.position))
            {
                down = true; changed = true;
            }
        }
        if (!changed) down = false;
        return down;

    }
}

With the game basically finished, I tried to publish to Google Play. This took a good few attempts, but I got there in the end. There is no real advice for this part, you just kind of hope it works! To be fair, google does send detailed info back if the app is rejected. When it was published, I got some advice for changes and added more tiles, including slopes, spikes and springs. I still have more to do on it, but am pleased with the outcome.

Leave a Reply

Your email address will not be published.