阶段学习总结-见缝插针案例

技术类技能学习就是需要多学习实例,多总结。今天又学习了一个见缝插针案例,特记录总结。

一.案例说明

  本案例是siki学院的免费课程,可以自行搜索。本案例是2D项目案例。

 

 二.效果图

 

游戏初始状态

 

 

游戏运行中

 

 

游戏结束

三.脚本说明

public class RotateSelf : MonoBehaviour
{
    //旋转速度
    public float rotateSpeed;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        //旋转
        transform.Rotate(new Vector3(0, 0, rotateSpeed * Time.deltaTime));
    }
}

首先是大黑圈会自动旋转,在其上挂载自动旋转脚本,这个脚本很简单,开放了旋转速度参数,在Update方法中旋转自身即可。

public class GameManager : MonoBehaviour
{
    //针的准备位置,需要使用空物体记录这个位置
    public Transform startPoint;
    //同样使用空物体记录针的生成位置,在游戏界面外部生成针,再使针移动到准备位置
    public Transform initiationPoint;
    //Pin是针上面挂载的脚本,上面有startFly方法,使实例化出来的针从实例位置向准备发射位置移动
    private Pin currentPin;
    //针的prefab
    public GameObject pin;
    //记录游戏是否结束的布尔值,游戏中两个针头发生碰撞游戏就会结束,这个布尔值是为了避免多个针实例重复调用游戏结束方法
    private bool isGameOver = false;
    //记录游戏分数(插上圆圈的针个数)
    private int score = 0;
    //实时显示分数
    public Text text;
    //主摄像机,在游戏结束时需要将摄像机镜头拉近,因此需要获取主摄像机上的camera组件,调整size属性值
    private Camera mainCamera;
    //游戏结束时需要将背景色渐变,使用线性插值Color.Lerp进行渐变,这里定义的时插值的第三个参数,初始值0.9变化会非常快
    public float colorChangeSpeed = 0.9f;
    // Start is called before the first frame update
    void Start()
    {
        //首先在屏幕外生成一个针并记录下来,针会自动向准备位置移动
        currentPin = Instantiate(pin, initiationPoint.position, pin.transform.rotation).GetComponent<Pin>();
        //获取摄像机
        mainCamera = GameObject.FindGameObjectWithTag("MainCamera").GetComponent<Camera>();
    }

    // Update is called once per frame
    void Update()
    {
        //如果游戏已经结束,不再更新
        if (isGameOver) return;
        //实时显示分数
        text.text = score.ToString();
        //当按下鼠标左键时
        if (Input.GetMouseButtonDown(0))
        {
            //按下鼠标左键后调用startFly方法,针开始从准备位置向黑球移动
            currentPin.startFly();
            //再次实例化一个针,并自动移动到准备位置
            currentPin = Instantiate(pin, initiationPoint.position, pin.transform.rotation).GetComponent<Pin>();
        }
    }

    //游戏结束方法
    public void gameOver()
    {
        //游戏已经结束就不再调用此方法
        if (isGameOver) return;
        else
        {
            //找到圆圈物体,禁用自动旋转组件,停止旋转
            GameObject.Find("Circle").GetComponent<RotateSelf>().enabled = false;
            //开启结束游戏的协程
            StartCoroutine(GameOverAnimation());
        }
        //记录下游戏已经结束
        isGameOver = true;
    }

    //加分,这个方法由针调用,当针到达指定位置并且针头没有和其他针头发生碰撞,调用此方法
    public void scoreCount()
    {
        score++;
    }

    //结束游戏的协程
    IEnumerator GameOverAnimation()
    {
        while (true)
        {
            //改变渲染的背景色
            mainCamera.backgroundColor = Color.Lerp(mainCamera.backgroundColor, Color.red, colorChangeSpeed * Time.deltaTime);
            //改变摄像机正交视野大小
            mainCamera.orthographicSize = Mathf.Lerp(mainCamera.orthographicSize, 4f, colorChangeSpeed * Time.deltaTime);
            //当视野改变和背景色改变完成后结束循环
            if(Mathf.Abs(mainCamera.orthographicSize - 4f) < 0.01f)
            {
                break;
            }
            yield return 0;
        }
        //暂停一秒
        yield return new WaitForSeconds(1);
        //重新加载场景
        SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);

    }
}

这段脚本用于管理游戏进程,主要包括计分、发射针和结束游戏等操作。脚本和针上面的控制针运动的脚本耦合性很高,两者相互调用较多,还有改善空间。

public class Pin : MonoBehaviour
{
    //记录针运动的速度
    public float speed = 5;
    //记录针是否已经发射并向目标位置运动,初始为false,下面会做if判断,在else语句中有针运动向准备位置的代码,即针实例化出来后立刻从初始化位置运动往准备位置
    private bool isFly = false;
    //记录针是否到达准备位置
    private bool isReach = false;
    //游戏中间的圆圈,针发射后需要到达的位置
    private Transform circle;
    //针的目标位置,即发射后需要到达的位置
    private Vector3 targetPosition;
    //针的起始位置
    private Transform startPoint;
    // Start is called before the first frame update
    void Start()
    {
        //初始化
        startPoint = GameObject.Find("StartPoint").transform;
        circle = GameObject.Find("Circle").transform;
        //计算针发射后需要到达的位置,在圆圈下方1.36处
        targetPosition = circle.position;
        targetPosition.y -= 1.36f;
    }

    // Update is called once per frame
    void Update()
    {
        //如果针在飞行,初始化出来的针这个值为false
        if (isFly)
        {
            //如果结束飞行说明针到达了准备位置,针就可以发射,在游戏管理脚本中按下鼠标左键后会将isFly的值设置为true,接下来针就会往发射目标位置飞行
            transform.position = Vector3.MoveTowards(transform.position, targetPosition, speed * Time.deltaTime);
            //如果飞行到达目标位置
            if (Vector3.Distance(transform.position, targetPosition) < 0.05)
            {
                //将真的位置设置为发射终点位置(最终针的到达位置和发射终点位置有微小的偏差)
                transform.position = targetPosition;
                //将针设置为圆圈的子物体,针将跟着圆圈一起旋转
                transform.parent = circle;
                //调用游戏管理的计分方法,记录分数
                GameObject.FindGameObjectWithTag("GameController").GetComponent<GameManager>().scoreCount();
                //设置针的状态为已经到达并没有在飞行
                isReach = true;
                isFly = false;
            }
        }
        //如果针没有在飞行,这里的飞行是指发射后向发射终点位置的飞行,值为false则针并未开始发射
        else
        {
            //判断针是否到达准备位置
            if (isReach)
            {

            }
            //针未到达准备位置则向准备位置运动
            else
            {
                //向准备位置运动
                transform.position = Vector3.MoveTowards(transform.position, startPoint.position, speed * Time.deltaTime);
                //如果到达准备位置,将是否到达准备位置的布尔值设置为true
                if(Vector3.Distance(transform.position,startPoint.position) < 0.05)
                {
                    isReach = true;
                }
            }
        }
    }

    //供游戏管理组件调用的方法,按下鼠标左键后会调用此方法,将是否飞行的布尔值设置为true,代表将向发射终点飞行
    public void startFly()
    {
        isFly = true;

    }

    //判断针头是否发生碰撞,如果碰撞则游戏结束
    private void OnTriggerEnter2D(Collider2D collision)
    {
        //针上设置了PinHead标签,通过标签判断碰撞到的位置是否是针头,如果是则将结束游戏
        if(collision.tag == "PinHead")
        {
            //调用游戏管理组件的游戏结束方法结束游戏
            GameObject.Find("GameManager").GetComponent<GameManager>().gameOver();
        }
    }

}

这段脚本用于管理生成的针prefab的运动和碰撞等。这段脚本逻辑复杂了一些,主要设置了两个布尔值,一个isFly代表针是否已经发射,一个isReach代表是否已经到达准备发射位置。刚生成的针的isFly初始值为false,isReach的值也为false,代表没有开始发射并且没有到达准备发射位置,在Update中做两次判断,双false的话针向准备发射位置运动。当按下鼠标左键时,不论针是否到达准备发射位置,isFly值都设置为true,代表针开始发射的飞行,飞行的终点位置为发射终点位置。因此代码Update方法中先判断isFly值看针是否已经发射,已经发射就使针向发射终点运动,如果未发射再判断针是否到达准备发射位置,未到达准备发射位置向准备发射位置运动。在发射到达发射终点后,再将isFly值设置为false,代表不用再飞行,同时设置isReach为true,不用再向发射准备位置运动。

 

posted @ 2020-11-27 23:15  movin2333  阅读(225)  评论(0编辑  收藏  举报