Enabling Touchpad Tap-To-Click in Kubuntu

Kubuntu, the KDE flavour of Ubuntu, seems to work very well out of the box when installed on a new machine, needing very little configuration. One instance where you need to take that extra step is to allow taps on a laptop touchpad to be interpreted as clicks. For some reason I can’t imagine, this is not enabled by default.

Note: I’m using Kubuntu 20.04 LTS with KDE Plasma 5.18.5.

To enable this, you need to go into System Settings -> Input Devices -> Touchpad. You can reach the Touchpad settings directly by searching for “touchpad” in the search box (top-left in System Settings).

In Touchpad settings, enable “Tap-to-click”.

Once in the Touchpad settings, all you need to do is enable the “Tap-to-click” option. Once this is enabled, there are additional settings you can customise, but there’s typically no need to change them.

Using Visual Studio Code with Unity3D on Linux

So you’ve set up Unity3D on Linux, but now you need a good text editor to write your scripts. In that case, you can consider using Visual Studio Code (VS Code for short), a cross-platform text editor from Microsoft. VS Code has become hugely popular for web development, but its versatility means that it can also be used for programming in languages such as C#, Python, Go, etc.

Note that I am using Linux Kubuntu 20.04 (LTS) and Unity3D 2020.3.15f2 (LTS).

Installing VS Code

The VS Code documentation explains how to set up VS Code on Linux. The easiest option is via the snap package manager as follows:

sudo snap install --classic code

Alternatively, you can download and install a .deb or .rpm package of you prefer. See the documentation for details.

Configuring the External Editor in Unity3D

Next, we’ll configure Unity3D to use VS Code as its external editor for scripts.

First, you’ll need to have the “Visual Studio Code Editor” package installed. This is set up for you when you create a new project, but you can double-check via the Window menu and then Package Manager:

Visual Studio Code Editor 1.2.3 is installed.

With that in place, go to the Edit menu and then Preferences… and switch to the External Tools tab. Click the dropdown next to the “External Script Editor” setting and then Browse… for the VS Code executable. If you don’t know where it is, use the following command in a terminal to locate it. In my case it’s at /snap/bin/code.

whereis code
To set VS Code as the Unity3D script editor, go to the Edit menu -> Preferences…, switch to the External Tools tab and then set the value of “External Script Editor” to the path to the VS Code executable.

Now, if you create a C# script in Unity3D and open it, it should open in VS Code.

Configuring VS Code for Unity3D

You can now write C# scripts for Unity3D in VS Code and you have syntax highlighting to help you. However, Intellisense — the helpful suggestions that pop up e.g. when you try to access an object’s properties — doesn’t work yet. You also don’t get any indication of C# syntax errors. Let’s fix this so that we can write Unity3D scripts in a comfortable environment.

First, install the .NET Core SDK on Linux by following the instructions in the relevant documentation.

Next, head to the Mono Download page, and follow the first set of instructions to add the Mono repository to your system. Then, for the second step, install mono-complete instead of mono-devel as shown below. (Note: don’t run the following command before first setting up the Mono repository. The version coming from the Ubuntu repositories doesn’t seem to play well with VS Code and Unity3D.)

sudo apt-get install mono-complete

Then, in VS Code, go to the Extensions tab on the left, search for “C#”, and install the first extension that comes up:

Install the C# extension for Visual Studio by Omnisharp.

Open up settings via File menu -> Preferences -> Settings (or Ctrl+, (control comma)) and search for “Omnisharp: Use Global Mono“, then set its value to “always”. Click “Restart Omnisharp” from the notification that appears at the bottom-right. You can also restart Omnisharp at any time by pressing Ctrl+Shift+P and selecting “OmniSharp: Restart OmniSharp”.

In Settings, set “Omnisharp: Use Global Mono” to “always” and then restart OmniSharp.

Still No Intellisense?

The above steps are usually enough to get Intellisense working, but as I’m writing this right now, it doesn’t seem to work. To fix this, I had to downgrade the C# extension in VS Code, as follows:

  1. Go into the Extensions tab in VS Code.
  2. Locate the C# extension by OmniSharp.
  3. Click the small arrow next to the “Uninstall” button.
  4. Select “Install Another Version…”
  5. In my case, the latest version (1.23.14) was released just 3 days ago. I went for an older version that had been around for a couple of months (1.23.12).
  6. Click the “Reload Required” button.
  7. Watch the Output and wait for OmniSharp to finish downloading and installing.

Testing Intellisense

VS Code should now provide Intellisense as you type, and you should also see syntax errors called out via both a squiggly red underline and in the Problems window below.

Intellisense and errors both work.

You should now be all set up. Happy game development!

Playing Painkiller on Linux

Painkiller is a little-known gem in the first-person shooter (FPS) genre. I’ve played through it many times, but my most recent playthrough had something different: I did it entirely on Linux (Kubuntu 20.04 LTS).

The view from the Old Monastery.

I recently wrote about how Warcraft 3 runs (almost) flawlessly on Linux. In this article I’ll give Painkiller a similar treatment.

Installing Painkiller

All along, I’ve been using the Painkiller Black Edition from GOG.com, which has a Windows-only installer of close to 4GB that you can download after purchasing the game.

Downloading the Painkiller installer from GOG.com.

Once downloaded, we can install the game by opening a terminal, navigating to the directory where it downloaded, and running the installer with WINE, as I’ve shown many times before in previous articles (note that that’s a single filename… the spaces should actually be underscores):

cd Downloads
wine setup_painkiller_black_1.64_lang_update_\(24538\).exe

This brings up the GOG installer for Painkiller, so you select the installation language, tick the box accepting the EULA, and optionally choose the folder to install to.

The GOG installer for Painkiller.

Click the Install button to begin the installation, and the installer runs into a snag towards the end:

This problem has happened to me with several GOG games before, and each time, I thought all was lost. So it was to my great surprise that, when I clicked the Launch button after closing the error, the game ran perfectly fine anyway.

I was able to play through the entire game without problems, so if you get this error while installing Painkiller (or another GOG game) with WINE, just ignore it and try playing anyway. Chances are it will be fine.

Playing the Game

You can run Painkiller by double-clicking the handy desktop icon it sets up for you. At that point, all that’s left is to enjoy the action and stunning visuals.

First Person Grid Movement with Unity3D

Before 3D took the gaming world by storm, many RPGs used a pseudo-3D engine in which you could move in discrete steps within a grid, with a first person view. Although this was popularised by “blobbers” such as Dungeon Master and Eye of the Beholder, it goes at least as far back as 1979 with Akalabeth.

Blobber: A slang term for party-based games with first-person view, such as Wizardry, Dungeon Master and Legend of Grimrock, where the entire party moves as one, as if it was an amorphous blob.”

The CRPG Book, page 522

Unity3D gives us everything we need to easily set up this first-person grid-based movement.

This article is based on Unity3D 2020.3.13f1 (LTS), and the source code is available in the Unity3dFirstPersonGridMovement folder of the Gigi Labs Bitbucket Repository.

Setting the Scene

First, create a new 3D project. Add a few Cubes to the scene so that we’ll have something to see as we move around. You can do this via GameObject menu -> 3D Object -> Cube, although after creating the first one, you can select it and press Ctrl+D to duplicate it. Set their X and Z positions to integer values, leaving their Y position set to zero. Since the Main Camera faces down the Z-axis, it’s also nice to not set X=0 for any cubes, so that we have a corridor that we can immediately walk down.

Added a few cubes to the scene.

Optionally, add a few different-coloured materials and apply them to the cubes. This will later help make the movement more obvious, rather than just having a long, solid white wall. Refer to “Simple Brick Wall with Unity3D” if you don’t know how to do this.

A bit of colour makes all the difference.

Finally, adjust the camera so that its Y-position is zero, aligning it with the cubes.

Implementing Movement

In my old article “Unity3D: Moving an Object with Keyboard Input“, I showed how Input.GetKeyDown() can be used to move an object when a key is pressed. We can use the same thing to move and rotate the camera.

Create a script called “Movement”, and drag it onto your Main Camera. Double-click the script to open it in an editor.

In the Update() method, add the following to enable the typical WASD keyboard movement (‘W’ to go forwards, ‘S’ to go backwards, ‘A’ to move left, and ‘D’ to move right, all while facing down the Z-axis):

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.W))
            this.transform.position += Vector3.forward;
        else if (Input.GetKeyDown(KeyCode.S))
            this.transform.position += Vector3.back;
        else if (Input.GetKeyDown(KeyCode.A))
            this.transform.position += Vector3.left;
        else if (Input.GetKeyDown(KeyCode.D))
            this.transform.position += Vector3.right;
    }

If you press Play, you can use the WASD keys to move around:

Moving forwards into the corridor.

Implementing Rotation

That was easy enough! The fact that the camera is conveniently aligned with the Z-axis allows us to use predefined vectors to move in specific directions. However, this is no longer the case once we allow rotation. Any movement must be done with respect to whatever direction the camera is currently facing.

Fortunately, we already know what direction the camera is facing. That’s its transform.rotation. We can change direction by multiplying it by a Quaternion, which we can conveniently create based on an angle in degrees using Quaternion.Euler(). Let’s see this in practice by allowing the ‘Q’ and ‘E’ keys to rotate the camera 90 degrees left and right, respectively:

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.W))
            this.transform.position += Vector3.forward;
        else if (Input.GetKeyDown(KeyCode.S))
            this.transform.position += Vector3.back;
        else if (Input.GetKeyDown(KeyCode.A))
            this.transform.position += Vector3.left;
        else if (Input.GetKeyDown(KeyCode.D))
            this.transform.position += Vector3.right;
        else if (Input.GetKeyDown(KeyCode.Q))
            this.transform.rotation *= Quaternion.Euler(0, -90, 0);
        else if (Input.GetKeyDown(KeyCode.E))
            this.transform.rotation *= Quaternion.Euler(0, 90, 0);
    }

The camera can now turn left and right:

I walked down the corridor and turned left.

However, this messes things up because the WASD keys still move with respect to the Z-axis, rather than in the direction that the camera is facing. We can easily fix this by multiplying the movement vectors by the camera’s rotation:

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.W))
            this.transform.position += this.transform.rotation * Vector3.forward;
        else if (Input.GetKeyDown(KeyCode.S))
            this.transform.position += this.transform.rotation * Vector3.back;
        else if (Input.GetKeyDown(KeyCode.A))
            this.transform.position += this.transform.rotation * Vector3.left;
        else if (Input.GetKeyDown(KeyCode.D))
            this.transform.position += this.transform.rotation * Vector3.right;
        else if (Input.GetKeyDown(KeyCode.Q))
            this.transform.rotation *= Quaternion.Euler(0, -90, 0);
        else if (Input.GetKeyDown(KeyCode.E))
            this.transform.rotation *= Quaternion.Euler(0, 90, 0);
    }

And this works really nicely.

I walked down the corridor, turned right, and moved a step backwards. I’m actually inside the red cube, because we have no collision detection!

Watch the demo video on YouTube to see this in action!

Wrapping Up

As we’ve seen, Unity3D makes it really easy to set up this simple game mechanic where you have a first person view, move in steps, and turn in 90-degree angles. It does help to be comfortable with vectors. If you’re not, check out my “A Concise Introduction to Vectors” [PDF] at Gigi’s Computer Corner.

If you’d like a little extra exercise, try to make the movement and rotations as smooth transitions. You can use Vector3.MoveTowards() and Quaternion.RotateTowards() for this. You’ll also need to change your camera’s near clipping plane to zero to avoid weirdness during rotations.

Simple Brick Wall with Unity3D

In Unity3D, we can use prefabs to create a template for an object that we’ll create many times, such as bullets, planets, or – as we’ll see in this article – bricks. Prefabs are handy because each instance will carry the same scripts, materials, transforms, etc. Let’s see how this works in practice by creating a wall made up of many bricks.

To start off, create a new 3D project with Unity3D. I’m using Unity3D 2020.3.13f1 (LTS), although any version is probably fine for this beginner exercise.

Creating a Brick Prefab

We’ll start off by creating a simple brick, which will be the building block for our wall.

Create a Cube, via the menu GameObject -> 3D Object -> Cube. Rename it to “Brick”. In the Transform portion of the Inspector, set the X component of its Scale to 2, so that it looks elongated like… a brick.

After creating a Cube GameObject, name it “Brick” and set its X-scale to 2.

Next, we’ll create a material for the brick. In your Project window, right click on Assets and then go Create -> Material. (You could create an appropriate folder structure to separate things like Materials, Scripts etc, but since we’ll have very few of these in this case, I won’t bother.) Name it “Brick Material”, and then set the colour of its Albedo property to something that looks like brick red (in my case I went with RGB(183, 50, 57)).

Name the material “Brick Material”, and set its Albedo to an appropriate colour.

Drag the Brick Material onto the Brick (in either the Hierarchy or Scene windows) to apply the colour.

Next, drag the Brick GameObject from the Hierarchy window to the Assets folder in the Project window to create a prefab out of it. Note how the Brick is now blue in the Hierarchy window, and it also gets an “Open Prefab” button in the Inspector.

Drag the Brick GameObject from the Hierarchy window to the Assets folder in the Project window. The Brick GameObject is now an instance of a prefab.

Instantiating a Single Brick

We now have two concepts of “Brick” in this project: the original Brick GameObject (as seen in the Hierarchy and Scene windows), and the Brick prefab (in the Assets folder of the Project window). The Brick GameObject is an instance of the Brick prefab. We can create more instances of the Brick prefab, and they will have the same components (such as materials and transforms) unless we specifically change them.

This makes it very easy to write a script to create lots of bricks using the Brick prefab as a template. In fact, we don’t need the Brick GameObject any more. Go ahead and delete it.

Right click on the Assets folder of the Project window, select Create -> C# Script, and call it WallGenerator. Double-click the script to open it in your script editor.

Add a serializable field for the Brick prefab at the beginning of the class:

public class WallGenerator : MonoBehaviour
{
    [SerializeField]
    GameObject brickPrefab;

Save the script, then go back to the Unity3D editor. Then:

  1. Drag the WallGenerator script onto your Main Camera.
  2. Notice the Brick Prefab property for the script in the Inspector.
  3. Drag the Brick prefab from the Project window into that slot in the Inspector.
Drag the WallGenerator script onto the Main Camera, and then drag the Brick prefab into the script’s relevant slot in the Inspector.

With this set up, we can start creating instances of the prefab from the script. Go back to the script editor, and add a call to Instantiate() in the Start() method as follows:

    // Start is called before the first frame update
    void Start()
    {
        Instantiate(brickPrefab);
    }

Back in the Unity3D editor, press Play to run the game. You’ll see that a brick is actually generated at runtime, even though we don’t have any in the Scene window in the editor:

A single brick, created by the WallGenerator script, is rendered in the scene at runtime.

Building a Wall

Now that we know how to create a single brick from a script, we can use simple loops to create more. Let’s create a 5×5 wall by using a different overload of Instantiate() that also takes a position (which we’ll provide) and rotation (which we’ll ignore):

    void Start()
    {
        for (int y = 0; y < 5; y++)
        {
            for (int x = 0; x < 5; x++)
            {
                Vector3 position = new Vector3(x * 2, y, 0);
                Instantiate(brickPrefab, position, Quaternion.identity);
            }
        }
    }

If you press Play, you’ll see the wall, although it’s a little hard to distinguish the bricks because they’re touching each other:

A 5×5 grid of bricks with no spacing in between, so it looks like one solid material.

You can tweak the scale of the Brick prefab to get some space between the bricks. For instance, this is how it looks with a scale of (X, Y, Z) = (1.95, 0.95, 1):

The brick wall with each brick having a scale of (X, Y, Z) = (1.95, 0.95, 1).

Finally, just to give it a bit more style, let’s change the script so that it generates alternating patterns of bricks:

    void Start()
    {
        for (int y = 0; y < 5; y++)
        {
            int xOffset = (y % 2 == 0) ? 1 : 0;

            for (int x = 0; x < 5; x++)
            {
                Vector3 position = new Vector3(x * 2 + xOffset, y, 0);
                Instantiate(brickPrefab, position, Quaternion.identity);
            }
        }
    }

All we did here was use the modulus operator (%) to check whether the row is an even-numbered one, and if so, add an extra 1 to the X position of each brick. This results in the following wall, better than any that Donald himself could ever hope to build:

A brick wall with alternating, slightly spaced bricks.

Summary

A prefab is a template of a GameObject used to create instances of it that share the same or similar components. As we have seen, we can easily call the Instantiate() method to create lots of instances of a GameObject from a script, making this one of the cornerstones of dynamic behaviour in Unity3D.

"You don't learn to walk by following rules. You learn by doing, and by falling over." — Richard Branson