Monthly Archives: January 2016

2d BB-8

The coolest new character in Star Wars Episode VII: The Force Awakens is BB-8, the droid that rolls on his spherical body with his head bopping along on top. It’s a great design and fun a character. Here’s how to achieve a 2D BB-8 in Unity.

BB-8

 

The Basics

The HeadMovement script is the part that is special to BB-8’s movement, and that is detailed below. Everything else is standard Unity basics, so to keep this tutorial short I won’t cover that. I’ve included a link to the completed project at the bottom, so you can look at the full code in there if you wish.

 

The Character

The Body

BB-8’s body is a circular sprite with a circle collider and rigidbody2d. I’ve tweaked its physics properties to get the right feel. We also have a simple player controller script that checks for left, right, and jump input.

The Head

The head itself is just a sprite and a script. The script checks the head’s position relative to the body and adjusts it to point in the right direction and ‘correct’ itself upright. Lerping is used to give the self-correcting a tangible, smooth feel.

Here’s the script code:

using UnityEngine;
using System.Collections;

public class HeadMovement : MonoBehaviour {

    [SerializeField]
    private Transform _bodyTransform;
    private Transform _headTransform;
    [SerializeField]
    private float distanceFromBody = 0.65f;
    private SpriteRenderer _headSprite;
    private float _lastPosX;

    void Start()
    {
        _headTransform = GetComponen<Transform>();
        _headSprite = GetComponent<SpriteRenderer>();
        _lastPosX = _bodyTransform.position.x;
    }

    void FixedUpdate()
    {
        _headTransform.position = Vector2.Lerp(_headTransform.position, new Vector2(_bodyTransform.position.x, _bodyTransform.position.y + distanceFromBody), 0.35f);
        _headTransform.rotation = Quaternion.Lerp(_headTransform.rotation, Quaternion.Euler(0, 0, 0), 0.35f);
        if ((_bodyTransform.position.x - _lastPosX) > 0.01f)
        {
            _headSprite.flipX = true;
        }
        else if ((_bodyTransform.position.x - _lastPosX) < -0.01f)
        {
            _headSprite.flipX = false;
        }
        _lastPosX = _bodyTransform.position.x;
    }
}

The idea behind the script is to maintain the correct angle and position. In FixedUpdate(), we do three things:

  1. Lerp the head’s position back to the point directly above the ball’s centre
  2. Lerp the head’s angle back to zero (upright)
  3. Make sure BB-8 is looking in the direction of the body’s movement.

 

That’s It

That’s all there is to it. You can tweak some of the settings to adjust the movement (and you can easily create better graphics than mine). If you find a way to improve this please share your ideas in the comments.

Stop Looking, You Already Found It!

Wherever Unity is discussed I see a mistake repeated by new Unity developers. It’s not a dumb or obvious mistake, but it can be a costly one. It’s the use of Unity’s ‘find’ functions to locate gameobjects and components inside update methods.

Here’s the kind of thing I’m talking about:

void Update()
{
    var player = GameObject.Find("Player").GetComponent<PlayerScript>();
    // do something with 'player'
}

That line of code is perfectly fine Unity code, but using it inside the Update() method is a big mistake…

Finding is slow

boxImagine your scene components (the player, the enemies, the scripts, etc.) are all in a big, disorganised box. When you use a finding method, like GameObject.FindGameObjectWithTag, Unity trawls through that box to find what you’re asking for. This is quite slow (for reasons I won’t go into). When a particular piece of code requires (relatively) lots of computing power we call it ‘expensive’, and it should be used carefully.

Repeating slow things is very slow

The Update() method in Unity games runs once per frame, so all code in Update() typically runs 30 to 60 times per second! The same applies to LateUpdate() and FixedUpdate(). Keep expensive code out of the update methods so it’s not repeated unnecessarily. If you need to make the player move in every frame, don’t do this:

void Update()
{
    var playerMove = GameObject.Find(“Player”).GetComponent<MoveScript>();
    playerMove.Move();
}

That code will work correctly, but it’s inefficient. What if you could just set the Player object aside somewhere Unity could grab it when needed instead of trawling through that big box?

Well you can. Simply create a variable in your script, then assign it to point to the object when your scene starts, in the Start() method:

MoveScript playerMove;

void Start()
{
    playerMove = GameObject.Find(“Player”).GetComponent<MoveScript>();
}

void Update()
{
    playerMove.Move();
}

In the Start() method the expensive search is done (once). From that point on, a reference to the relevant script is easily accessible in the playerScript variable. You’re no longer searching for it during every frame.

When I say GameObject.Find and its relatives are expensive, this is relatively speaking. You should not avoid using them entirely, and they won’t affect performance in most cases.

Caching References

You should also apply this to getting components of the current gameobject. Instead of calling this every time you need to access the rigidbody2d:

var rbody = gameObject.GetComponent<RigidBody2D>();

Cache that variable in Start() and then use rbody to access the rigidbody2d.

Looping

You should also avoid costly searching in loops. Consider the following:

for (int i=0; i < 200; I++)
{
    var player = GameObject.Find("Player");
    Player.DoSomething();
}

and:

var player = GameObject.Find("Player");

for (int i=0; i < 200; I++)
{
    player.DoSomething();
}

In the first example Unity searched through the big box of components 200 times, but in the second example the slow search is done once.

Now imagine if you put that first loop in Update()! You’d be doing a costly component search 200 times every frame. That would be 6,000 calls (at 30 fps) every second (if your device can keep up).

Cleaner Code

A side benefit of caching references is that it helps keep your code clear. You assign a value to player once, and it can be accessed throughout your script. Your methods and functions don’t need to find objects for themselves, and your code is easier to read and maintain.

 

Summary

Finding game components and objects using Unity’s built-in functions (‘finds’ and ‘gets’ like GameObject.Find and GetComponent) is slow. Using those functions is not in itself troublesome; in fact, they are invaluable tools. But you should never repeatedly search for the same items when you can search once and ‘remember’ the object by caching a reference (usually at the beginning of the scene in Start()), and then use the reference whenever you need to access the object.