Sunday, March 18, 2018

Testing Touch Input with Mouse

When developing a game for mobile, it is beneficial to be able to test input on the computer before deploying to the mobile device.  In the case of testing a single tap on the screen, the OnMouseDown function will work as a single tap on the mobile device.

In this way, you can test single taps on the computer through mouse clicks, and it will still work once it's deployed.  For more complex touch inputs such as multi-finger and dragging, you'll want to use the Input.GetTouch functions.

Saturday, July 8, 2017

Gaming Textures for Models

Adding textures for models is an important technique for adding a lot of detail to an object without using a lot of polygons.  See my blog entry for how to achieve this in Blender:  Texturing for Gaming Models


Static UI

Some basics with using UI in Unity 5.  To get a static (non-interactive) UI element, go to GameObject > UI  and either select Text or Raw Image.


Adding one of these will automatically create a Canvas and an EventSystem.  For static purposes these two game objects can be ignored.  Note that the order at which the child objects appear will dictate what is "in front" of what in the view.  In this case CountBackground is behind the Text.


Final note, if referencing these objects within code make sure you have the header:

using UnityEngine.UI;

Global vs Local

There are times when it is beneficial to work either in what is referred to as Local or Global space.  This manifests itself in a few places.  In the editor, you may have seen these buttons.  They toggle where the center point of an object is [Center/Pivot], and the transform reference [Local/Global]

 

As an example of the distinction, Center will place the transform marker at the average center of the object including the shape of its children.  To the contrary, the Pivot will place the center at what I would call the "center reference" as defined in the original model.

In the same way Local and Global refer to the reference in space for the transform.  This can be most easily seen in the available transform functions.

  • eulerAngles/localEulerAngles
  • position/localPosition
  • rotation/localRotation
  • scale/localScale
Specifically with child objects, using one or the other makes a significant difference in behavior.  Making changes to the global transform of a child object will control it irrespective of what the parent is doing whereas local changes are relative to what the parent is doing.

List of Collided

As far as I can tell Unity doesn't have a mechanism natively that tells you all the objects that are currently collided (triggered) in your collider.  The most common approach seems to be managing the list on your own using the OnTriggerEnter and OnTriggerExit:

    void OnTriggerEnter(Collider other)
    {
        if (other.tag == "enemy")
        { 
            allCollisions.Add(other.gameObject);
        }
    }

    void OnTriggerExit(Collider other)
    {
        if (other.tag == "enemy")
        {
            allCollisions.Remove(other.gameObject);
        }
    }

One extra point to note, that this approach breaks down if your objects are "exiting" because they are destroyed.  In my case, I wanted to destroy the entire list of objects via an event.  At first I used List.Clear(), however I found that this only nulls all the elements, but doesn't actually clear the elements.  Better was to blow away the list with a new instance.

if (Input.GetButtonDown("Fire1"))
{
   foreach (GameObject enemy in allCollisions)
   {
SeekToKill newBullet = (SeekToKill)Instantiate(bullet, bulletStart.transform.position, bulletStart.transform.rotation);
newBullet.SetTarget(deadbug);
   }

   // clear list including indicies
   allCollisions = new List<GameObject>();
}

OnTriggerEnter Re-entrance

This is more of a lessons-learned while developing a game, and I'm creating a post as a reminder for myself.  In this scenario I was using the OnTriggerEnter function to determine when the object would be destroyed.

The issue I was running into was that in some rare cases, multiple objects would trigger this function simultaneously, causing this function to call multiple times before the object was actually destroyed.

Adding a class flag solved my issue, in my case I called it isDead:

    private void OnTriggerEnter(Collider other)
    {
        if (other.tag == "Bullet" && !isDead)
        {
            Destroy(this.gameObject);

            system.UpdateBugCount(-1);
            isDead = true;
        }
    }

The flag prevents re-executing the function after the object should technically be destroyed.

Multi-Player Input

In a multiplayer scenario, at times it is beneficial to distinguish between different input designations and assign them specifically to a player.  In this case, I had a game where one player controlled the vehicle and another player controlled the gun turret on the back.  In this scenario, I needed certain input to be dedicated to a specific player.

To do this in Unity for an Axis Input, set the Joy Num field to a specific player.


For a Button Input, add the term "joystick #" in the button field rather than just stating "joystick".  Using just "joystick" actually allows all controllers to trigger that input.