Learning Game Dev #1: OnPointer vs Mouse, Orthographic camera, deltaTime, and 2D Sprites.

I though would be interesting to keep track of the blockers I found this week when developing my snake-lookalike mini game project , some may find a solution to a current problem they’re having, and I may be helpful for myself in the future as well.

First of all, here’s a quick video of the differences in the work in progress between May 13th (10 first seconds) and May 20th (rest of the video):

Ngu development May 13-20

Make builds as soon as possible, and keep doing them during all your development process

Functions may differ when porting your game between platforms, after creating the player movement behaviour both in keyboard (so I’m able to play test on the Unity editor) and touchscreen I moved into testing it directly on iOS to discover that, surprise surprise, not only some elements of the UI were overlapping the screen touches and actions where not triggered, but also the control responsiveness was delayed.

This means I just invested a couple of hours in creating a player control behaviour that was only working on desktop (where the game is not intended to be launched), but was unplayable in mobile, the platform that was intended to. Imagine if I discover this hundreds of hours in.

Later on I discovered that in Unity, by default, the button events that are executed by screen touch events default to the MouseUp() method, not to the OnClick() method as in Desktop, this is important because means that the event is not triggered when you touch the screen, but when the finger is lifted, even if the Editor says otherwise as the event will be routed via MouseUp(). You still can see how this is supposed to be triggered OnClick(), which you may falsely assume that is when your finger touches the screen, but is not:

This was fixed by using OnPointerDown() and OnPointerUp() instead, following a solution I found in the Unity forums here , I added a new script to the controls that simple checks if OnPointerDown() or OnPointerUp() happens, switch a boolean to false/true, do a validation check within Update() and triggers the player movement. This means that will happen even if MouseUp() hasn’t finished as is independent, making the control responsiveness on point. The snippet:

    public class InstantTouchBehaviour : MonoBehaviour, IPointerDownHandler, IPointerUpHandler{

        MoveByTouch moveByTouchScript;
        bool _pressed = false;

        public void Start()
        {
            moveByTouchScript = GetComponent<MoveByTouch>();
        }

        //Detect current clicks on the GameObject (the one with the script attached)
        public void OnPointerDown(PointerEventData eventData)
        {
            _pressed = true;
        }

        //Detect if clicks are no longer registering
        public void OnPointerUp(PointerEventData eventData)
        {
            _pressed = false;
        }

        void Update()
        {
            if (_pressed)
            {
                moveByTouchScript.MoveItRight();
            }
        }

    }

Your game will look extremely different on different devices

I get that nobody has multiple devices to test things through, that’s why you should build and share alphas and betas of your game as soon as possible. During the first week I was building the game on a completely wrong UI/UX setup, once I tested in my iPhone everything was just wrong.

Remember to switch the Unity Editor to a base resolution and screen ratio that fits your testing device, and then keep in mind that you’ll need to create something to adapt the camera and resolution to different devices, based on where you plan to launch.

In this game I’m using 2D and Pixel Art, so things may be different than other types of games, but following the PPU (Pixel per unit) equation: Camera orthographic size = vertical resolution / PPU / 2 , I got that using 32 pixel sprites and testing on an iPhone 5s in Portrait mode (1136px long) I should use an Camera orthographic size of 17.75

The funny part is that before finding this equation and calculating it correctly, I did it manually just by moving the camera around and testing on my mobile to see when it was looking fine, and I left it at 18, which is pretty near to the correct calculated value.

Then you will need to add this somehow to a device detection statement via Screen.width and Screen.height , so will look good for all mobile devices but I’m still working on this so have no code to share for the moment.

Understanding Time.deltaTime

At the core of every game there’s a game loop, which is active as long as the application is running. Depending on the machine the application is running on, there can be varying number update passes during a given time frame, e.g. you can have varying frame rates based on the machine configuration. This will really mess things up if you don’t have a way to synchronise all your updates somehow to the real physical time.

Time.DeltaTime in Unity Script. This is simply a parameter which tells you how much time has passed since the last time your script’s Update was invoked

– Source: Someone in the internet, lost the original link.

This is extremely important if you want to keep game speed consistency within machines, where a second will be a second everywhere.

Understanding technical, time, and scope limitations

I experimented a bit with the general art direction I wanted to follow with the game before deciding and setting for a specific style, while at first I was all in for a “minimalistic” style based heavily in low poly meshes, particles, and shaders, there was a problem with this: I have no idea how to do 3D or vectorial art, neither how to create shaders, and my particles are pretty bad.

While this may be treated as a learning opportunity, not only particles and shaders may be a performance killer for a mobile game, but I’m already trying to learn C# and Unity, adding more things to the pot is the perfect recipe for burnout, project abandonment, and disaster.

After spending a few days playing with Blender, vectorial software, and checking shader tutorials I moved on completely into something I know better, pixel art and 2D animations. I will learn and use the initial style in the future for other projects or demos, but currently this did not fit my technical, time, or scope limitations and I moved as fast as possible from it, before investing too much into it.

During my research I found this channel that is pure gold if you want to understand how make things look good, or the math behind shaders and other graphical stuff. Hasn’t been updated forever though, is a pity:

Optimizing 2D Sprites

From different forums/explanations/tutorials I got these basic pointers for any 2D/Pixel game:

  • Traditionally screens were 72 DPI. Today high-DPI screens are usually 144 DPI, but you can find phones that boast up to 400 DPI or more since they are packing a lot of pixels on relatively small screens. Something to think about.
  • Turn off antialiasing from your Project Settings, for all the different qualities individually! (See screenshot below)
  • Filter mode Point: No Filter
  • Compression: none
  • Use a consistent Pixel per unit (PPU), so you won’t have camera/resolution problems. Check the PPU equation above.
Anti Aliasing may be enabled/disabled based on different levels of Quality, be sure to deactivate it for all of them (Very Low, Low, Medium, … )

Save your snippets, add comments, and reuse code

Lots of little bits of code comes from my previous unfinished project where I already figured out a solution for the same problems a year ago, but I wouldn’t remember right now. For example:

  • Camera Shake
  • Item pickup collisions
  • Score and HighScore functionality
  • Muzzle flash effect
  • GameOver functionality and screen/ replay vs quit
  • Blink effect
  • Floating “combat” text

Remember to call your functions, and do it in the right order.

Easy right? Who would write a function and then not call it? Well, is not the first time I’ve spent 2 hours debugging something to discover that the function was never called, or was called in the wrong place.

Creating a Pulse

When I was playing with the art style I decided to create a method that basically creates a pulse with its textures, size, shape, etc,… this pulse can be used for example to increase/decrease the size of an object, to change its color, etc, … in this particular case I used it for the background, the pulse affects the background alpha value making it totally transparent and totally opaque every 10 seconds, and you can see how its transparency is altered smoothing through both extremes during these 10 seconds. I’m not entirely sure if I will end using it, but here’s the initial code:


      IEnumerator MapColorPulse()
        {
            bool isLimitReached = false;

            map = GameObject.Find("Map");
            SpriteRenderer mapRendererComponent = map.GetComponent<SpriteRenderer>();
            initialMapAlphaValue = mapRendererComponent.color.a; // 1

            while (true)
            {
                if (initialMapAlphaValue > 0.1 && isLimitReached == false) // decrease alpha
                {
                    initialMapAlphaValue = initialMapAlphaValue - 0.1f;
                    if (initialMapAlphaValue < 0.1)
                    {
                        isLimitReached = true;
                    }
                }

                else if (initialMapAlphaValue < 1 && isLimitReached == true) // increase alpha
                {
                    initialMapAlphaValue = initialMapAlphaValue + 0.1f;
                    isLimitReached = true;
                }
                else if (initialMapAlphaValue >= 1)
                {
                    isLimitReached = false;
                }

                float newMapAlphaValue = initialMapAlphaValue;
                mapRendererComponent.color = new Color(1, 1, 1, newMapAlphaValue);

                yield return new WaitForSeconds(1f);
            }
        }

We’ll start this with a coroutine like StartCoroutine(MapColorPulse()); via for example the Start() method, or any other trigger we want. As long as the limit is not reached, it will increase/decrease the alpha value of the SpriteRenderer, when the limit is reached, will do the opposite of what was doing.

In this case is specifically created for changing the background alpha, but can be easily modified following the same concept to change any other attribute of any object in a pulse fashion.

And that’s all about it for now! Let me know if you found this interesting so I can think about publishing these type of posts on a recurrent basis.

Join 244 other subscribers

Comments

Leave a Reply

Discover more from Home

Subscribe now to keep reading and get access to the full archive.

Continue reading