Let’s Make: Legend of Zelda- Step 02: Create the Player

A. Lynn Ferguson
6 min readMay 15, 2021

--

Time to get the Player to at least move. If only a little.

Review the To-Do List:

By the time I was done reviewing my “Game Document” (the actual game itself, in my case), and making my GameManager’s Singleton code, I actually had a short to-do list already made.

The global data in the game, that forever needs to be monitor is:

  • The Player
  • Camera Setup ( and Utilities).
  • Player Location (to power a map function and control who is spawning)
  • The Player Data (lives, weapons, quest items, and money)
  • The GUI/Sub-menu

These are by no means the only to-do items. Just a start. Also, I re-arranged them by order of priority, starting with the most critical piece first — The Player. Because if there is no player, what is a game even for? Right? We’ll probably start setting up pieces of the camera too.

Pro-Tip: Being able to sort and prioritize your work into micro-steps (preferably ones that can be accomplished in a day or so) is critical skill for any professional programmer. Not only is it easier to submit smaller features to GitHub, but it’s incredibly satisfying to say you checked one or two things off your list, versus getting “some progress” on a giant would-be feature.

With this To-Do list in front of us, we can tell our first steps are going to be making the Player script, and at least getting it to move. Even if that movement is simple, it’s going to be progress.

Image from: Kill Bill.

1 ). Create a Player Script, and tell the GameManager about it

To reiterate, the Player is a global piece of data that will be forever present during the session of the game. There is literally no such thing as “Legend of The Person Watching Baddies on a Screen But That’s It”. So let’s add it to the Game Manager.

  1. Create a new C# script, and call it Player. It’s okay for this to be blank for now.
  2. Create an empty game object, and also call it Player. Attach the script.
  3. Now open up the GameManager and add the following: public Player player;
  4. After Unity compiles, click on the GameManager. Note that it now has a “Player” field. Drag and drop your newly made Player game object on top of that field.

Wallah. Now the GameManager knows what the Player is. And since the GameManager has a Static accessor, any other script in this game will have the ability to instantly dial into it, by writing GameManager.Instance.player. Note that in this specific case, because I made the playera public field, that is the reason why any script accessing the GameManager, will also see the Player. If I made the player a [SerializeField] private field, I’d be able to assign it in the Inspector, but other scripts wouldn’t have access to it.

I’m choosing to make it Public in this case, because there’s a good chance other scripts (like the camera) will need to know about the Player, what it is, and where it’s at.

2 ). Art: What does the player look like?

But first, a note about the start of most projects.

Here’s the ugly truth — at this point in your project, you wouldn’t have any finalized art/graphics/sprites. Instead, you would use a series of plain white boxes (or white squares in our case, because the game is 2D), and thesew ould be your placeholders until the artists finished the graphics/sprites/etc. This is specifically why some programmers refer to this as the “White Boxing” stage, or the “Alpha” stage. You won’t quite know what your game looks like yet. But you can still form the scripts that dictate how your game behaves.

  1. Click on your Player game object. Add a Sprite Renderer component. Keep everything at default. Sprite Renderer will tell Unity that you’re going to be displaying a 2D image from this object, but that it’s otherwise interacting in a 3D space, and has a regular Transform (not RectTransform, which is 2D only)
  2. For now, we’re just going to leave this guy a white square. You can choose a default sprite graphic, like UISprite, which comes with any basic project. I’m using a basic, tiling white square sprite. But it doesn’t really matter what you use yet since you’ll be changing it.
The Player so far; it ain’t pretty to look, but the truth is that this is how most game projects start.

3 ). Make the Player Move

Now it’s time to make the Player move.

There are two strategies we can leverage for this. 1 ). Translate code, and 2 ). RigidBody code. Both have pros and cons.

Movement using Translate

Translate tends to be simpler to code, and requires little more than access to the object’s Transform. If you’re doing very little with a game object (moving it side to side but nothing else), then it’s faster to code it as a Translate. But Translate doesn’t provide much else to work with. It doesn’t know when the player has stopped. It can’t necessarily leverage physics. Etc. If you’ve started any of the learning tracks on Unity Learn, you’ve probably see this kind of Player Movement in use. I’ve certainly used it a time or two. But in this case, the player is a little more complicated.

Movement using RigidBody

RigidBodies tend to require a little more for setup, and also involve the Unity physics engine. Because of this, it can provide details like when the player has stopped; when it’s been struck; and these are data bits we can use to change the player animation cycle on demand. Therefore, we’re going to use RigidBodies.

  1. Add a Rigidbody2D. Everything will remain default, except for the Gravity Scale field. Change that to 0. Since Legend of Zelda is a top-down game, we’re not going to be using gravity. Note: If you’re doing a regular, horizontal, 2D platformer, you need to keep Gravity Scale the same.
  2. Also add a Box Collier 2D. And again, keep it default for now.
  3. Open the Player script again. It’s time to tell Unity about how we want our player to move, and at what speed.
  4. Player Speed: Write [SerializeField] private float MovementSpeed. Anytime you’re making something move, you need to give Unity a speed. You can set a default in script by writing = 5; at the end. Serializing this float means I can edit it via the Unity Inspector, but it’s still otherwise private.
  5. Player RigidBody and Movement: Below speed, also write [SerializeField]RigidBody2D playerRigidBody; and then below that, write [SerializeField] Vector2 playerMovement;. Again, the SerializeField attribute means you can see these in the Inspector, which can be very useful for Debugging.
  6. Inside of Inspector, drag and drop the Player GameOject on top of where it says “Player Rigid Body.” You could also automatically assign this in the Player’s Awake function too, by writing the following:
    if ( playerRigidBody == null )
    {
    playerRigidBody = GetComponent<RigidBody2D>();
    }

    What this script does, is it checks if the player rigid body has been assigned yet. If it hasn’t, it tries to grab it from the same object the Player.cs script is on. But it at least first checks if you assigned in Inspector to begin with.
  7. Connect the Player Key Presses: Most player sprites move when the gamer presses a combo of buttons, like the infamous WASD combination and if not that, at least the default arrow keys should do the trick. In fact, this is so standard that Unity has defaulted horizontal/vertical input to these keys already. So all you need to write is a few lines of code under Update().
    private void Update()
    {
    playerMovement.x = Input.GetAxisRaw("Horizontal");
    playerMovement.y = Input.GetAxisRaw("Vertical");
    }

    Unity has a default Input system that already knows what Horizontal and Vertical is. You can change it of course, and read more about it here. But this is all we need for LoZ. So with this code in Update, Unity will know to expect player WASD/arrow input. And knows where to plug those in at.
  8. We’re not done yet though. RigidBody2D leverages Unity physics. So we also have to put some code into the FixedUpdate(); function, which specifically talks to the physics of a game.
    private void FixedUpdate()
    {
    playerRigidBody.MovePosition(playerRigidBody.position +
    playerMovement.normalized * playerSpeed * Time.fixedDeltaTime);
    }

    With this code in FixedUpdate, Unity will apply movement and magnitude to your player’s RigidBody. If it seems to be going slow, you can slide the player speed float upward, to make it fast.

Save. Let Unity compile. Once you press play, if you set everything up right, your player will now be moving! Grant it, it’s just a white box, but it’s still progress. If you do nothing else in your hobby project for the day, you still made progress.

If you get any errors though, and need help, drop me a line.

--

--

A. Lynn Ferguson

A. Lynn Ferguson is a Prototyper III with Facebook Reality Labs and a quintessential child of the internet who loves all things media and digital. With a degree