Unity之见缝插针游戏

535 阅读4分钟

1.UI界面

(1)导入资源 在这里插入图片描述

(2)首先这是一个2d游戏,应把模式转化为2d模式,并且调整摄像机的两个属性为SolideColor 和orth0graphic (正交模式),

在这里插入图片描述

(3)制作针(针头为针身的子对象),并且创建两个空组,并给两个空组一个颜色,并分别命名为Level,Start,分别表示针生成的位置和针准备射击的位置,并计算针射到圆盘上圆盘中心和和针中心的距离。我这里距离为1.34 (4)拖动针,使其变成一个预制体。并删除地图上现有的针。

2.射击系统

创建一个脚本命名为Shoot,挂载到刚开始创建的Level空组上,并添加以下脚本,然后先暂时跳到子弹处理系统。


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Shoot : MonoBehaviour
{
    
    
    public Transform GunBullet;//定义一个预制体组件
    bool isnoMouse;//定义一个布尔变量判断接收鼠标左键是否按下

    void Start()
    {         
        Creat();              
    }

    // Update is called once per frame
    void Update()
    {             
        isnoMouse = Input.GetMouseButtonDown(0);//鼠标左键按下一次返回true,否则返回false
        if (isnoMouse)
        {        
            Creat();//创建针
        }
    }

    void Creat()
    {
        GunBullet = Instantiate(GunBullet, transform.position, GunBullet.transform.rotation);//初始化针
    }  
    
}



3.子弹处理系统

(1)创建一个脚本命名为GunBullet挂载到UI部分制作的子弹预制体上,并添加以下脚本,

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GunBullet : MonoBehaviour
{
    bool isReach;  //用于判断子弹是否准备完毕
    bool isFay;   //用于判断子弹是否开始飞行
    float Speed; //用于控制子弹飞行的速度    
    Transform Circle;//用于储存圆盘
    Vector3 position;//用于储存子弹最终要到达的位置
    Transform start;//用于储存start空组

    void Start()
    {
        Speed = 0.4f;
        Circle = GameObject.Find("Circle").transform;//获取圆盘
        start = GameObject.Find("Start").transform;//获取start空组
        //计算子弹最终要到达的位置
        position = new Vector3(Circle.position.x, Circle.position.y - 1.34f, Circle.position.z);
        isReach = false;
        isFay = false;

    }
    void Update()
    {
        //当子弹不需要发射时
        if (isFay == false)
        {
            //且子弹还未准备完毕时
            if (isReach == false)
            {                
                //让子弹移动到准备发射的地方
                transform.position = Vector3.MoveTowards(transform.position, start.position, Speed);
                if (Vector3.Distance(transform.position, start.position) < 0.04f)
                {
                    //当到达准备发射的地方时,让子弹变为准备完毕的状态
                    isReach = true;
                }
            }
        }
        else
        //当按下鼠标左键将会调用射击系统将会调用StartFay方法使其变为发射状态
        {
            //让子弹移动到最终要到达的位置
            transform.position = Vector3.MoveTowards(transform.position, position, Speed);
            if (Vector3.Distance(transform.position, position) < 0.04f)
            {
                //当到达最终要到达的位置时,改变他的状态,此后一直会在  不需要发射且准备完毕状态,也就是一直在33行
                isFay = false;
                //忽略偶然误差带来的不便
                transform.position = position;
                //把子弹的父对象设为圆盘使其和圆盘一起转动(后续会补上圆盘转动的脚本)
                transform.parent = Circle;

            }
        }
    }
    /// <summary>
    /// 改变子弹的状态,使其向最终的点移动
    /// </summary>
    public void StartFay()
    {
        isReach = true;
        isFay = true;
    }

}

然后更新Shoot脚本如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Shoot : MonoBehaviour
{
    
    
    public GunBullet gunBullet;//定义一个预制体组件
    bool isnoMouse;//定义一个布尔变量判断接收鼠标左键是否按下
     Transform newgunBullet;//储存由预制体生成的子弹
    void Start()
    {         
        Creat(); //创建第一个子弹             
    }

    // Update is called once per frame
    void Update()
    {             
        isnoMouse = Input.GetMouseButtonDown(0);//鼠标左键按下一次返回true,否则返回false
        if (isnoMouse)
        {
            //使当前子弹从准备状态变为发射状态,并创建下一个针,注意24行和25行的顺序不能乱,
            //不然新创建的针永远都只会是发射状态
            gunBullet.GetComponent<GunBullet>().StartFay();
            Creat();

        }
    }

    void Creat()
    {
        gunBullet = Instantiate(gunBullet, transform.position, gunBullet.transform.rotation);//初始化子弹
    }  
    
}



然后在补齐圆盘转动的脚本,创建脚本名为Rota的脚本并挂到圆盘上。脚本如下

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Rota : MonoBehaviour
{
    public static float Speed;//圆盘旋转速度
   public static float direction;//圆盘旋转方向
    // Start is called before the first frame update
    void Start()
    {
        direction = 1f;
        Speed = 3f;
    }

    // Update is called once per frame
    void Update()
    {

        transform.Rotate(new Vector3(0, 0, direction) * Speed );
    }

}

在这里插入图片描述

4.死亡处理

然后我们发现当针头和针头碰撞时游戏并不会结束,因此新建脚本fail挂载到预制体的针头上,并且我们还要给针头增加2d刚体和2d盒型碰撞器。并把刚体的gravity Scale设置为0,以及盒型碰撞器的is Trigger勾上。 在这里插入图片描述

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Colllier : MonoBehaviour
{
   
    private void OnTriggerEnter2D(Collider2D collision)
    {      
        GameObject.Find("Level").GetComponent<Shoots>().Gameover();
    }
}

注意这个脚本的作用主要是为了触发射击系统的Shoot脚本的Gameover()方法,所以我们应该先更新Shoot脚本。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class Shoot : MonoBehaviour
{

    bool isStop;//用于判断是否停止射击
    public GunBullet gunBullet;//定义一个预制体组件
    bool isnoMouse;//定义一个布尔变量判断接收鼠标左键是否按下
     Transform newgunBullet;//储存由预制体生成的子弹
    Camera mainCamera;
    void Start()
    {
        isStop = false;
        mainCamera = Camera.main;
        Creat(); //创建第一个子弹             
    }

    // Update is called once per frame
    void Update()
    {
        if (isStop)
        {
            return;
        }
        isnoMouse = Input.GetMouseButtonDown(0);//鼠标左键按下一次返回true,否则返回false
        if (isnoMouse)
        {
            //使当前子弹从准备状态变为发射状态,并创建下一个针,注意24行和25行的顺序不能乱,
            //不然新创建的针永远都只会是发射状态
            gunBullet.GetComponent<GunBullet>().StartFay();
            Creat();

        }
    }

    void Creat()
    {
        gunBullet = Instantiate(gunBullet, transform.position, gunBullet.transform.rotation);//初始化子弹
    }

    public void GameOver()
    {
        //44和49这种结构是为了不让GameOver()重复执行
        if (isStop == true) return;
        
        GameObject.Find("Circle").GetComponent<Rota>().enabled = false;//让圆盘重复执行
        StartCoroutine("GetEnumerator");//使用协程,让背景逐渐变红,屏幕放大(实际上是对摄像机的一些操作)

        isStop = true;
    }
    IEnumerator GetEnumerator()
    {
        while (true)
        {
            //对摄像机的背景进行插值运算。
            mainCamera.backgroundColor = Color.Lerp(mainCamera.backgroundColor, Color.red, 3f * Time.deltaTime);
            mainCamera.orthographicSize = Mathf.Lerp(mainCamera.orthographicSize, 3.5f, 3f * Time.deltaTime);
            if (Mathf.Abs(mainCamera.orthographicSize - 3.5f) < 0.04f)
            {
                break;
            }

            yield return 0;//返回每次插值运算后摄像机的状态。

        }

        yield return new WaitForSeconds(1f);//等待1秒
       SceneManager.LoadScene( SceneManager.GetActiveScene().buildIndex);//加载当前场景
    }
}

最后我们增加分数显示。在编辑界面创建一个文本框,注意要调Canvas的模式,调至合适的大小并拖至圆盘中心,然后我们想要的效果是针到圆盘后加分,并且为了增大难度,我们可以设置当针到达圆盘让圆盘加速并随机变向。所以Shoot脚本和Gunbullet脚本更新如下。 在这里插入图片描述

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class Shoot : MonoBehaviour
{

    bool isStop;//用于判断是否停止射击
    public GunBullet gunBullet;//定义一个预制体组件
    bool isnoMouse;//定义一个布尔变量判断接收鼠标左键是否按下
     Transform newgunBullet;//储存由预制体生成的子弹
    Camera mainCamera;
    public static int grade;
    public Text score;
    void Start()
    {
        isStop = false;
        mainCamera = Camera.main;
        Creat(); //创建第一个子弹     
        grade = 0;
        score.text = grade.ToString();
    }

    // Update is called once per frame
    void Update()
    {
        score.text = grade.ToString();
        if (isStop)
        {
            return;
        }
        isnoMouse = Input.GetMouseButtonDown(0);//鼠标左键按下一次返回true,否则返回false
        if (isnoMouse)
        {
            //使当前子弹从准备状态变为发射状态,并创建下一个针,注意24行和25行的顺序不能乱,
            //不然新创建的针永远都只会是发射状态
            gunBullet.GetComponent<GunBullet>().StartFay();
            Creat();

        }
    }

    void Creat()
    {
        gunBullet = Instantiate(gunBullet, transform.position, gunBullet.transform.rotation);//初始化子弹
    }

    public void GameOver()
    {
        //44和49这种结构是为了不让GameOver()重复执行
        if (isStop == true) return;
        
        GameObject.Find("Circle").GetComponent<Rota>().enabled = false;//让圆盘重复执行
        StartCoroutine("GetEnumerator");//使用协程,让背景逐渐变红,屏幕放大(实际上是对摄像机的一些操作)

        isStop = true;
    }
    IEnumerator GetEnumerator()
    {
        while (true)
        {
            //对摄像机的背景进行插值运算。
            mainCamera.backgroundColor = Color.Lerp(mainCamera.backgroundColor, Color.red, 3f * Time.deltaTime);
            mainCamera.orthographicSize = Mathf.Lerp(mainCamera.orthographicSize, 3.5f, 3f * Time.deltaTime);
            if (Mathf.Abs(mainCamera.orthographicSize - 3.5f) < 0.04f)
            {
                break;
            }

            yield return 0;//返回每次插值运算后摄像机的状态。

        }

        yield return new WaitForSeconds(1f);//等待1秒
       SceneManager.LoadScene( SceneManager.GetActiveScene().buildIndex);//加载当前场景
    }
}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GunBullet : MonoBehaviour
{
    bool isReach;  //用于判断子弹是否准备完毕
    bool isFay;   //用于判断子弹是否开始飞行
    float Speed; //用于控制子弹飞行的速度    
    Transform Circle;//用于储存圆盘
    Vector3 position;//用于储存子弹最终要到达的位置
    Transform start;//用于储存start空组

    void Start()
    {
        Speed = 0.4f;
        Circle = GameObject.FindGameObjectWithTag("Player").transform;//获取圆盘
        start = GameObject.Find("Start").transform;//获取start空组
        //计算子弹最终要到达的位置
        position = new Vector3(Circle.position.x, Circle.position.y - 1.34f, Circle.position.z);
        isReach = false;
        isFay = false;

    }
    void Update()
    {
        //当子弹不需要发射时
        if (isFay == false)
        {
            //且子弹还未准备完毕时
            if (isReach == false)
            {                
                //让子弹移动到准备发射的地方
                transform.position = Vector3.MoveTowards(transform.position, start.position, Speed);
                if (Vector3.Distance(transform.position, start.position) < 0.04f)
                {
                    //当到达准备发射的地方时,让子弹变为准备完毕的状态
                    isReach = true;
                }
            }
        }
        else
        //当按下鼠标左键将会调用射击系统将会调用StartFay方法使其变为发射状态
        {
            //让子弹移动到最终要到达的位置
            transform.position = Vector3.MoveTowards(transform.position, position, Speed);
            if (Vector3.Distance(transform.position, position) < 0.04f)
            {
                //当到达最终要到达的位置时,改变他的状态,此后一直会在  不需要发射且准备完毕状态,也就是一直在33行
                isFay = false;
                //忽略偶然误差带来的不便
                transform.position = position;
                //把子弹的父对象设为圆盘使其和圆盘一起转动(后续会补上圆盘转动的脚本)
                transform.parent = Circle;
                Shoot.grade++;
                if (Random.Range(0, 2) == 0)
                {
                    Rota.direction = -1f;
                }
                else
                {
                    Rota.direction = 1f;
                }
                Rota.Speed += 0.2f;

            }
        }
    }
    /// <summary>
    /// 改变子弹的状态,使其向最终的点移动
    /// </summary>
    public void StartFay()
    {
        isReach = true;
        isFay = true;
    }

}

最后游戏制作完成。