In this tutorial, we will continue on what we created in the previous tutorial.
I. Making the camera follow the player
The first thing we want to do is to make the camera follow the player. Find the Standard Assets (Mobile) script folder:
Now, drag the script named SmoothFollow2d and set it on the Main Camera:
You should now see it added as a component of the camera:
Now, we need to set the target to the player. Drag the Player GameObject from the hierarchy to the target property of the component:
If you press play now, the camera will center on the player object.
II. Controlling the player
Create a new script in our Scripts folder and name it “PlayerHandler”.
Drag it on the Player GameObject in the hierarchy view and make sure it’s added:
Now, edit this script. Our goal is to move it up and down by input, and then we are walking forward automatically. How should we control the character? First of all, this is going to be an app for both tablets and phones, so touch/mouse is essential. At a later tutorial, we will add keybaord and Xbox360 controller support too (easy to do! ).
This script is a start, covering the touch/mouse input:
using UnityEngine;
using System.Collections;
public class PlayerHandler : MonoBehaviour {
float speed = 4.0f;
public GameObject go;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
Vector3 movePlayerVector = Vector3.right;
if (Input.GetMouseButton(0))
{
Vector3 touchWorldPoint = Camera.main.ScreenToWorldPoint(
new Vector3(Input.mousePosition.x,
Input.mousePosition.y,
10.0f));
if (touchWorldPoint.y >= this.transform.position.y)
{
movePlayerVector.y = 1.0f;
}
else movePlayerVector.y = -1.0f;
}
this.transform.position += movePlayerVector * Time.deltaTime * speed;
}
}
First of all we create a vector that’s pointing right. This vector is then added to the players position later. This means that we are always walking right. This vector is 1.0 on the X-axis and 0.0 on the Y-axis.
We need to modify this vector with the Y-axis to make our character move up and down.
We check for input from the left mouse button (the same as a touch point). If it is being pressed, take the mouse coordinate and convert it to world view (since when we click the mouse/touch the screen, the position of the location we touched is in screen-space (screen resolution). We need to convert it to world space (the same coordinate system that our player is in).
Now, it’s hard to see anything without a background. Let’s add this!
III. Adding the background
This section will cover how to add a background to our game.
a) First, add a new quad to our scene:
d) Create a new material and name it “BackgroundMaterial”:
e) Set the texture of the material to the “Background.png” texture in “Textures\Environment”:
f) Set the shader to Mobile/Background:
The reason for this is that we don’t want any lighting on our scene, since it’s 2D. This shader will just use the colors set when creating the image using your favorite drawing application.
g) Set the scale of the Background GameObject to the same aspect as the texture resolution, something that fit the scene. We also set the Positions Z azis to one, so it’s a bit behind our player:
The result should be something like this:
IV. Looping the background
Next we need to loop the background. We want an infinite world. We could duplicate the Background GameObject many times and line them up together, or we can make a prefab out of it, and then use a script to draw a lot of them!
Create a new folder in the Assets/Game folder and name it Prefabs:
Next, create a new C# script in the Scripts-folder named EnvironmentHandler:
Drag this script on the Main Camera GameObject.
Now, browse to the Prefabs-folder:
Then drag the Background GameObject from the scene hierarchy to the Prefabs-folder to create a prefab out of it:
Then delete the Background GameObject from the scene hierarchy:
Now, open the EnvironmentHandler-script, and write the following code:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class EnvironmentHandler : MonoBehaviour {
public GameObject BackgroundPrefab;
public GameObject Player;
List<GameObject> spawnedBackgrounds = new List<GameObject>();
int spawnIndex = 2;
// Use this for initialization
void Start () {
for (int i = 0; i < spawnIndex; i++)
{
spawnedBackgrounds.Add(
(GameObject)Instantiate(BackgroundPrefab,
new Vector3(i * 51.2f + 25.6f, 0, 0.01f),
Quaternion.identity)
);
}
}
// Update is called once per frame
void Update()
{
bool addNewBackground = false;
foreach (GameObject bgObject in spawnedBackgrounds)
{
if (bgObject != null)
{
if (bgObject.activeInHierarchy)
{
float distanceFromPlayer =
Player.transform.position.x – bgObject.transform.position.x;
if (distanceFromPlayer > 51.2f)
{
Destroy(bgObject);
bgObject.SetActive(false);
addNewBackground = true;
}
}
}
}
if (addNewBackground)
{
spawnedBackgrounds.Add(
(GameObject)Instantiate(BackgroundPrefab,
new Vector3(spawnIndex * 51.2f + 25.6f, 0, 0.01f),
Quaternion.identity));
spawnIndex++;
}
}
}
Oh, another script that looks complex! Again, I wrote this to have a simple code so it would be easy to understand the goal and logic of it, not efficient so if you need a place to optimize, this is a place to test out (but it should be good enought ).
So… what is this script doing?
It’s simple – what we want is to render two backgrounds on our scene. If one background is behind us, remove it and spawn a new infront of us.
When we start the level, two Background GameObjects are spawned. These are positioned at the scenes origin (where the player starts) – 25.6f. This number is the width of the background game object divided by two. This is to make sure that we don’t get half the screen empty in the first run like this:
The image shows the blue area where there isnt yet a part of our background object since they havent scrolled there yet (or the player havent moved away from the start position yet). By subtracting this, we move all the background objects 25.6f to the left.
Next, we check the distance of the backgrounds behind the player, and if any of them are further away than 51.2 (that’s the length of the entire background gameobject), we remove it and tell the code that we want to add a new in front.
spawnIndex is used to remember where in the world we are.
On the Main Camera where the EnvironementHandler script is attached, drag the new Background-prefab to the Background Prefab property, and our Player-prefab to the Player property:
Now, test to see if we are moving forward, and that you can move the player up and down with the mouse/touch-screen.
V. Making sure the camera is “inside” our environment
As you probably see, we can move the player outside of the invironment. And even if we don’t, some of the environments edges are inside of the view, making it possible to see the blue background color of our scene.
It’s time to remove this artifact, something we will do on the script that we attached to our Main Camera earlier.
Click on the Main Camera GameObject, and edit the script attached to it by doubleclicking it:
Change the script with the following modifications:
#pragma strict
var target : Transform;
var smoothTime = 0.3;
private var thisTransform : Transform;
private var velocity : Vector2;
function Start()
{
thisTransform = transform;
}
function Update()
{
thisTransform.position.x = Mathf.SmoothDamp( thisTransform.position.x,
target.position.x, velocity.x, smoothTime);
thisTransform.position.y = -0.5;
}
This will lock the cameras Y-axis to the given position.
Try running the scene again and we can see that the camera is now placed on –0.5 on the Y-axis (this coordinate was found by trail and error based on where the sidewalk on the texture is).
VI. Making sure our player is on the sidewalk
The last thing we will do today is to make sure the player is inside the sidewalk. We do this the same way as with the camera, but inside the PlayerHandler-script. Here we will limit the minimum and maximum value of the players Y-position.
This is very simple. We check that the player is between –2.0 and – 5.5 (found by trial and error). If you press Play on the scene, move the player to the top part of the sidewalk:
..and then click the Player in the scene hierarchy to view the properties, you can see that Y is around –2.0. This is the method I used to create these bounds.
using UnityEngine;
using System.Collections;
public class PlayerHandler : MonoBehaviour {
float speed = 4.0f;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
Vector3 movePlayerVector = Vector3.right;
if (Input.GetMouseButton(0))
{
Vector3 touchWorldPoint = Camera.main.ScreenToWorldPoint(
new Vector3(Input.mousePosition.x,
Input.mousePosition.y,
10.0f));
if (touchWorldPoint.y > this.transform.position.y)
{
movePlayerVector.y = 1.0f;
}
else movePlayerVector.y = -1.0f;
}
this.transform.position += movePlayerVector * Time.deltaTime * speed;
if (transform.position.y > -2.0)
{
transform.position = new Vector3(transform.position.x,
-2.0f,
transform.position.z);
}
if (transform.position.y < -5.5)
{
transform.position = new Vector3(transform.position.x,
-5.5f,
transform.position.z);
}
}
}
Now, pressing play again – you can see that we can move our robot up and down, he is kept between the bounds of the sidewalk and the camera is inside the environment.
The last thing we want to do is to set the target of our player a bit in front of us, so that we can see longer in to the scene than what we can do now.
Right now it’s:
This is simple. Add a new empty GameObject to our scene and drag it inside our Player Game Object. Give it the name “CameraTarget” and position position to 6,0,0
a) Create the GameObject, put it inside the player and set the name to CameraTarget
Next, we set this as the target for our SmoothFollow2d script on our Main Camera.
Click the Main Camera GameObject:
Drag the CameraTarget from the Hierarchy to the target property of the script:
Now, run the game again and you can see that our visibility is much better!
In the next tutorial, we will create the enemies and spawn them. We will also make is possible to shoot them with our laser!
Pingback: Unity for Windows VIII–Creating a more advanced game, Part 3 | digitalerr0r
Everything else worked fine, but backgrounds are not extended to infinite. Only first two are laid out properly..