–通过移动世界而不是移动角色来模拟endless的效果。
–在摄像机外回收并循环资源,节约性能。
–障碍通过脚本对象池实现,性能更好。

1.GetMouseButtonDown()
button values are 0 for left button,
1 for right button,
2 for middle button.

2.OnCollisionEnter2D ()
如果附加了此脚本的游戏对象,与其它东西发生碰撞,则会调用此函数。

3.SetTrigger(“nameOfTrigger”,)
可以传入我们想要设置的触发器(多用于动画触发)

4.SetActive(ture or false)
可以触发或关闭组件。

5.重新加载场景。
using UnityEngine.SceneManagement;空间声明。
void Update()
{
if (GameOver == true && Input.GetMouseButtonDown(0))
{
SceneManager.LoadScene (SceneManager.GetActiveScene ().buildIndex);//加载一个场景文件
}
}

6.调用UI
空间声明:
using UnityEngine.UI;

7.对象池
这是一种软件创建设计模式,使用一组准备好使用的初始化对象作为一个池,而不是实时的分配和销毁对象。
池的客服端从池中请求一个对象,并对返回的对象执行操作,当客服端完成操作后,它将对象返回到池中而不是销毁,它将手动或自动完成。
对象池主要用于性能,在某些情况下,对象池可以显著提高性能,这对于游戏开发来说是绝对实用的。
对象池使对象在周期内变得复杂,当从池中获取或返回对象时,实际上并未创建或销毁对象,因此在使用过程中需谨慎。
所以如果它是一个复杂的对象,你可能需要有某种复位函数,以确保一切都重置,当它回到对象池的时候。这全都取决于你的游戏和你的对象。

主功能:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;//引入UI,记录分数

public class GameControl : MonoBehaviour
{
    public static GameControl instance; //强制对象为单例模式,允许它从我们的任何其它脚本中访问
    public GameObject GameOverText;
    public bool GameOver = false;
    public float scrollSpeed = -1.5f;
    public Text scoreText;
	
    private int score = 0;
	
    void Awake()
    {
        if (instance == null)
        {
            instance = this; //当初始化时,确保没有其它gamecontrol
        }
        else if (instance != this)
        {
            Destroy (gameObject);//意味着破坏此脚本所附加的游戏对象
        }
    }

    void Update()
    {
        if (GameOver == true && Input.GetMouseButtonDown(0))
        {
            SceneManager.LoadScene (SceneManager.GetActiveScene ().buildIndex);//加载一个场景文件
        }
    }

    public void BirdScored ()
    {
        if (GameOver)
        {
            return;
        }
        score++;
        scoreText.text = "Score: " + score.ToString ();
    }

    public void BirdDied()
    {
        GameOverText.SetActive (true);
        GameOver = true;
    }
}

角色控制器
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BirdController : MonoBehaviour
{
    public float addForce = 200f;

    private Rigidbody2D rb2d;
    private bool isDead = false;
    private Animator anim;
    void Start()
    {
        rb2d = GetComponent<Rigidbody2D>();
        anim = GetComponent<Animator>();
    }

    void Update()
    {
        if (!isDead && Input.GetMouseButtonDown(0)) //鼠标左键。
        {
            rb2d.velocity = Vector2.zero; //重置速度为0,平衡力
            rb2d.AddForce(new Vector2(0, addForce));
            anim.SetTrigger("Flap");
        }
    }

    void OnCollisionEnter2D() 
    {
        rb2d.velocity = Vector2.zero;
        isDead = true;
        anim.SetTrigger("Die");
        GameControl.instance.BirdDied ();
    }
}

卷轴
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ScrollingObject : MonoBehaviour
{
    private Rigidbody2D rb2d; 
    void Start()
    {
        rb2d = GetComponent<Rigidbody2D>();
        rb2d.velocity = new Vector2(GameControl.instance.scrollSpeed, 0);
    }

    // Update is called once per frame
    void Update()
    {
        if (GameControl.instance.GameOver == true)
        {
            rb2d.velocity = Vector2.zero;
        }
    }
}

复制实现卷轴循环
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RepeatingBackground : MonoBehaviour
{
    private BoxCollider2D groundCollider;
    private float groundHorizontalLength;

    void Start()
    {
        groundCollider = GetComponent<BoxCollider2D>();//引入碰撞体
        groundHorizontalLength = groundCollider.size.x;//获得x轴的大小
    }
     
    void Update()
    {
        if (transform.position.x < -groundHorizontalLength)//检查是否需要重新定位
        {
            RepositionBackground ();
        }
    }

    private void RepositionBackground()
    {
        Vector2 groundOffset = new Vector2(groundHorizontalLength * 2, 0);
        //在重新定位它的时候我们向前迈进了多少距离。
        transform.position = (Vector2) transform.position + groundOffset;//计算移动多远

    }
}

引入计分
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Column : MonoBehaviour
{
    private void OnTriggerEnter2D (Collider2D other)
    {
        if (other.GetComponent<BirdController>() != null) ;//无论通过什么触发器,检查它是不是鸟
        {
            GameControl.instance.BirdScored ();
        }
    }
}

对象池
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ColumnPool : MonoBehaviour
{
    public int columnPoolSize = 5;//表示数组初始长度的值。
    public GameObject columnPrefab;//实例化的对象
    public float spwanRate = 4f;//在玩家面前从对象池放置新柱子的时间间隔。
    public float columnMin = -1f;
    public float columnMax = 3.5f;//以垂直随机偏移量定位柱子

    private GameObject[] columns;//柱子数组。
    private Vector2 ObjectPoolPosition = new Vector2(-15f, -25f);//一个屏幕外的位置
    private float timeSinceLastSpawned; //储存自上一次在玩家面前放置一个柱子以来,已经过了多少时间。
    private float spawnXPosition = 10f;
    private int currentColumn = 0;//跟踪正在重新定义数组中的柱子

    void Start()
    {
        columns = new GameObject[columnPoolSize];//用5个空对象制作了一个新的空数组游戏对象
        for (int i = 0; i < columnPoolSize; i++)
        {   //循环遍历我们索引的每一个对象,实例化Prefab,实例化的位置是ObjectPoolPosition,Quaternion.identity设置预制体的旋转
            columns[i] = (GameObject) Instantiate(columnPrefab,ObjectPoolPosition,Quaternion.identity);
            //实例化一个对象为游戏对象,储存在数组中
        }
    }

    void Update()//计时器
    {
        timeSinceLastSpawned += Time.deltaTime;

        if (GameControl.instance.GameOver == false && timeSinceLastSpawned >= spwanRate)
        {
            timeSinceLastSpawned = 0;
            float spawnYPosition = Random.Range(columnMin, columnMax);//生成柱子
            columns [currentColumn].transform.position = new Vector2(spawnXPosition, spawnYPosition);
            //生成了一个固定的x坐标,随机的y坐标;
            currentColumn++;
            if (currentColumn >= columnPoolSize)
            {
                currentColumn = 0;
            }
        }
    }
}