unity3d实现简单的打飞碟游戏

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/sodifferent/article/details/101980559

游戏内容

游戏有n个round,每个round发射10次trial,每个trial的飞碟都可能不同,包括速度角度得分等,使用鼠标进行射击,点中即表示射击成功。

游戏要求

使用带缓存的工厂模式来管理飞碟的生产与再利用,工厂使用单例模式。

游戏的设计

  1. 首先是设计一个制造飞碟的工厂
    由于需要使用带缓存的工厂,所以使用两个list来储存正在使用的飞碟,与没有使用的飞碟。每次需要工厂输出一个飞碟的时候就去未被使用的链中寻找相应的飞碟,如果有就直接拿到正在使用的飞碟的链中,并返回;如果没有就需要创建一个相应的飞碟,并放入正在使用的飞碟的链中。这样在一开始会不断的创建飞碟,但是创建之后的飞碟并没有被删除,而是存起来了,简单的将其active设置为false即可,这样就被隐形了,再次使用的时候初始化一下位置即可,达到循环使用的目的。下面给出工厂中生产飞碟的代码:
public GameObject getufo(int round)
    {
        ufo s = new ufo();
        GameObject ufo_ = null;
        string type_ = getufotype(round);

        for(int i = 0; i < rest.Count; i++)
        {
            if (rest[i]._ufo.gameObject.tag == type_)
            {
                ufo_ = rest[i]._ufo;
                rest.Remove(rest[i]);
                ufo_.gameObject.SetActive(true);
                break;
            }
        }

        if (ufo_ == null)
        {
            if (type_ == "u1")
            {
                ufo_ = Instantiate(Resources.Load<GameObject>("ufo_u1"), bottom, Quaternion.identity);
            }
            else if (type_ == "u2")
            {
                ufo_ = Instantiate(Resources.Load<GameObject>("ufo_u2"), bottom, Quaternion.identity);
            }
            else
            {
                ufo_ = Instantiate(Resources.Load<GameObject>("ufo_u3"), bottom, Quaternion.identity);
            }
            //ufo_.GetComponent<ufo>().direction = new Vector3(1, 1, 0);
            ufo_.tag = type_;
            int r = Random.Range(0, 1);
            s.direction = new Vector3(0, r, 0);
            s._ufo = ufo_;
        }
        ufo_.transform.position = bottom;
        s._ufo = ufo_;
        use.Add(s);
        //Debug.Log("in have " + use.Count);
        return ufo_;
    }

这里的tag是对飞碟对象的一个标记,这里用了3种飞碟,所以只使用3个tag即可,对于tag的使用需要自己去添加
在这里插入图片描述
在这里插入图片描述
这样就可以直接设置了。

然后是对飞碟的回收:

public void free(GameObject ufo_)
    {
        for(int i = 0; i < use.Count; i++)
        {
            if (ufo_.GetInstanceID() == use[i]._ufo.gameObject.GetInstanceID())
            {
                use[i]._ufo.gameObject.SetActive(false);
                rest.Add(use[i]);
                use.Remove(use[i]);
                break;
            }
        }
    }

使用GetInstanceID来确认需要回收的飞碟是链中的哪一个,找到之后将其从使用链中删去,再添加到未使用链中,同时设置其不可见。

  1. 设计控制游戏的运行类,即导演
    在这个控制类中需要有一个工厂来持续生产飞碟,然后还需要再设计一个集合来储存需要运行的飞碟,这里其实可以直接调用工厂里的正在使用的链,但是为了做到尽可能少的耦合,就分开来处理。
    对于飞碟的运动在update函数中实现,这点很简单。然后是对每个trial的设置,需要对两个trial之间的间隔时间进行控制,然后每次trial根据一个规则输出数量不同的飞碟。然后将工厂中拿到的飞碟放到之前说的那个集合中,表示场景中正在使用与运动的飞碟。接着调用移动的函数,让飞碟按照既定的路线运动,具体代码如下:
void Update () {
        Debug.Log(r.finish());
        if (r.finish() == true)
        {
            textmesh.text = "finish and your score is: " + r.getScore();
            restart();
            while (flyufo.Count > 0)
            {
                remove(flyufo[0]);
            }
        }
        if (r.getStart() == true && r.finish() == false)
        {
            textmesh.text = "round " + r.getround() + " score: " + r.getScore();
            interval += Time.deltaTime;
            if (interval > 2f)
            {
                r.nextTrial();
                //int left = number - flyufo.Count;
                int left = r.getNumberOfufo();
                //Debug.Log(fac.use.Count);
                for (int i = 0; i < left; i++)
                {
                    //display.Add(fac.getufo(1));
                    flyufo.Add(fac.getufo(r.getround()));
                    float x = Random.Range(-2f, 2f);
                    float y = Random.Range(0f, 1f);
                    float z = Random.Range(1f, 2f);
                    //Debug.Log("" + x);
                    dir.Add(new Vector3(x, y, z));
                }
                interval = 0;
            }
            //Debug.Log("out have " + fac.use.Count);
            ti += Time.deltaTime;
            for (int i = 0; i < flyufo.Count; i++)
            {
                if (i <= shownum)
                {
                    move(flyufo[i], dir[i]);
                }
                if (ti > 2f)
                {
                    shownum++;
                    ti = 0;
                }
            }
            if (Input.GetButtonDown("Fire1"))
            {
                Vector3 mousePosition = Input.mousePosition;
                Ray ray = cam.ScreenPointToRay(mousePosition);
                RaycastHit hit;
                if (Physics.Raycast(ray, out hit))
                {
                    r.addscore(hit.transform.gameObject.tag);
                    remove(hit.transform.gameObject);
                }
            }
            outscreen();

            //Debug.Log("now round " + r.getround() + " trial " + r.gettrial() + " score " + r.getScore());
        }
    }

在每次运动之后还需要判断一下飞碟是否飞出视野,一旦飞碟飞出了一段距离就需要判定它消失(当然不能给射击者加分),如果不处理这个问题的话,飞碟就会一直存在,一直飞下去,也无法得到重用,玩家也无法将其射中,这样就会耗费资源,降低游戏效率
在这里插入图片描述

  1. 对规则的控制
    对于每个round输出的飞碟与飞碟的分数等信息都需要一个规则来控制,这里对规则的设计很简单,也包括对游戏的运行的控制。具体内容见代码即可。

  2. UI的一些显示
    这里使用了一个text来显示游戏的得分等相关信息,具体设计如下。
    首先得到这个文本框
    在这里插入图片描述
    注意这里需要对游戏中建立的空对象添加相应的组件
    在这里插入图片描述
    在这里插入图片描述
    添加这个text mesh,然后就可以在游戏中调用并对它进行设置了。
    其设置内容的方法与位置如下
    在这里插入图片描述

然后是添加一个开始按钮
在这里插入图片描述

用户的点击射击
在这里插入图片描述
这里模拟一条射线来射击,调用Raycast来查看是否射中,射中的对象就是hit,然后对这个对象进行操作即可。这里使用的cam是一个camera,在start中进行初始化,为主摄像机
在这里插入图片描述

  1. 单例模式的使用
    直接将老师提供的代码ctrl c加ctrl v,然后直接调用即可。
    在这里插入图片描述

至此整个游戏的设计完成,下面是游戏运行中的截图
在这里插入图片描述

项目地址

猜你喜欢

转载自blog.csdn.net/sodifferent/article/details/101980559