STAY INFORMED
following content serves as a personal note and may lack complete accuracy or
certainty.
Minimal-Mistakes instruction
Useful vscode Shortcut Keys
Unix Commands
npm Commands
Vim Commands
Git Note
Useful Figma Shortcut Keys
Flappy Bird Clone
Background
Rendered two background prefabs and they move to left. When background posX reach to out of the frame, reset posX
public class Background : MonoBehaviour
{
[SerializeField] private float moveSpeed = 5f;
void Update()
{
transform.position += Vector3.left * moveSpeed * Time.deltaTime;
if (transform.position.x < -2.3f){
transform.position = new Vector3(20.5f, 1.9f, 0);
}
}
}
Player
Jump
Player simply jumps when clicked. Unity provides physics features, so I just need to add a Rigidbody 2D component to the player and configure it.
public class Player : MonoBehaviour
{
[SerializeField] private float jumpForce = 3f;
private Rigidbody2D rb;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
if (Input.GetMouseButtonDown(0)) // mouse-left click
{
Jump();
}
}
void Jump()
{
rb.velocity = Vector2.up * jumpForce;
}
}
Collision
When the player goes off the screen or collides with a pipe, it dies.OnTriggerEnter destroys the player if it collides with an object tagged ‘Dead’.
private void OnTriggerEnter2D(Collider2D other){
if (other.gameObject.CompareTag("Dead")){
Destroy(gameObject);
}
}
Pipe Spawner
Created a spawner that spawns a pipe at a random Y position within the frame
public class Spawner : MonoBehaviour
{
[SerializeField] private GameObject pipes;
private float maxY = 2.8f;
private float minY = -2.6f;
void Start()
{
StartCoroutine(SpawnPipe());
}
private IEnumerator SpawnPipe(){
while (true){
float spawnY = Random.Range(minY, maxY);
Instantiate(pipes, new Vector3(transform.position.x, spawnY, transform.position.z), Quaternion.identity);
yield return new WaitForSeconds(3f);
}
}
}
Pipe
The pipe itself gets destroyed when its posX moves outside the frame.
public class Pipe : MonoBehaviour
{
[SerializeField] private float moveSpeed = 1f;
void Update()
{
transform.position += Vector3.left * moveSpeed * Time.deltaTime;
if (transform.position.x < -4.5f){
Destroy(gameObject);
}
}
}
And there is an empty objects which has ‘Score’ tag between pipes so when player pass between two pipes, user get a score.
Game Manager
Scene Load
Scene Load functions(main menu scene, game playing scene(restart))
public void Restart(){
SceneManager.LoadScene("GameScene");
}
public void BackMainMenu(){
SceneManager.LoadScene("MainScene");
}
Get best score from unity local storage when start.
void Start()
{
// reset
score = 0;
if (scoreText != null){
scoreText.gameObject.SetActive(true);
}
// get value of best score from unity local storage, if null, set to 0
bestScore = PlayerPrefs.GetInt("BestScore", 0);
}
Declare a toggle function which switches isPaused boolean variable, and this variable is checked in update function.
public void TogglePause()
{
isPaused = !isPaused;
pausePanel.gameObject.SetActive(isPaused);
}
In Update function, check isPaused, is Player dead, and convert score text to string.
public class Score : MonoBehaviour
{
void Update()
{
scoreText.text = score.ToString();
Time.timeScale = isPaused ? 0 : 1;
if (!player){
GameOver();
}
}
}
This function is called when player pass between the pipes.
public void AddScore()
{
score++;
}
When gameover, check is current score greater than best score, and if yes, update it.
private void GameOver(){
scoreText.gameObject.SetActive(false);
endScoreText.text = score.ToString();
if (score > bestScore){
bestScore = score;
newRecord.gameObject.SetActive(true);
PlayerPrefs.SetInt("BestScore", bestScore);
}
bestScoreText.text = bestScore.ToString();
// hide pause button
PauseBtn.gameObject.SetActive(false);
// show game over panel
panel.SetActive(true);
Four different medals are displayed depending on the score.
if (score >= 40){
Medal.sprite = platinum;
}
else if (score >= 30){
Medal.sprite = gold;
}
else if (score >= 20){
Medal.sprite = silver;
}
else if (score >= 10){
Medal.sprite = bronze;
}
else{
// if score is less than 10, no medal
Medal.gameObject.SetActive(false);
Medal.sprite = null;
}
}
Before the application quits, save best score on local storage
void OnApplicationQuit()
{
PlayerPrefs.SetInt("BestScore", bestScore);
}