打飞碟小游戏

这次的主要任务是写一个打飞碟的小游戏,熟悉一下之前的MVC模式和动作分离,可以复用一部分前面的代码。

游戏场景截图

这次建立了一个简单的天空盒和地面。场记依旧加载到空对象GameObject上,并且控制飞碟加载。

代码组织结构

  1. 这次代码的核心是Disk和DiskFactory,也就是用工厂模式来控制物体的产生和复用。

    • Disk类:储存了一些基本属性,并且可以通过这些属性直接修改gameObject的属性。
        public class Disk : MonoBehaviour {public Vector3 StartPoint { get { return gameObject.transform.position; } set { gameObject.transform.position = value; } }public Color color { get { return gameObject.GetComponent<Renderer>().material.color; } set { gameObject.GetComponent<Renderer>().material.color = value; } }public float speed { get;set; }public Vector3 Direction { get { return Direction; } set { gameObject.transform.Rotate(value); } }}
    • DiskFactory类:Disk的道具工厂,减少游戏对象的销毁次数,复用游戏对象,且屏蔽创建和销毁的业务逻辑,使程序易于扩展。具体在这个代码中,DiskFactory还负责在生产Disk时随机指定起始位置,方向,速度,颜色。

    public class DiskFactory { //开始时继承了MonoBehaviour后来发现不继承也可以public GameObject diskPrefab;public static DiskFactory DF = new DiskFactory();private Dictionary<int, Disk> used = new Dictionary<int, Disk>();//used是用来保存正在使用的飞碟 private List<Disk> free = new List<Disk>();//free是用来保存未激活的飞碟 private DiskFactory(){diskPrefab = GameObject.Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/disk"));//获取预制的游戏对象diskPrefab.AddComponent<Disk>();diskPrefab.SetActive(false);}public void FreeDisk(){foreach (Disk x in used.Values){if (!x.gameObject.activeSelf){free.Add(x);used.Remove(x.GetInstanceID());return;}}}public Disk GetDisk(int round)  {FreeDisk();GameObject newDisk = null;Disk diskdata;if (free.Count > 0){//从之前生产的Disk中拿出可用的newDisk = free[0].gameObject;free.Remove(free[0]);}else{//克隆预制对象,生产新DisknewDisk = GameObject.Instantiate<GameObject>(diskPrefab, Vector3.zero, Quaternion.identity);}newDisk.SetActive(true);diskdata = newDisk.AddComponent<Disk>();int swith;/** * 根据回合数来生成相应的飞碟,难度逐渐增加。*/float s;if (round == 1){swith = Random.Range(0, 3);s = Random.Range(30, 40);}else if (round == 2){swith = Random.Range(0, 4);s = Random.Range(40, 50);}else {swith = Random.Range(0, 6);s = Random.Range(50, 60);} switch (swith)  {  case 0:  {  diskdata.color = Color.yellow;  diskdata.speed = s;  float RanX = UnityEngine.Random.Range(-1f, 1f) < 0 ? -1 : 1;  diskdata.Direction = new Vector3(RanX, 1, 0);diskdata.StartPoint = new Vector3(Random.Range(-130, -110), Random.Range(30,90), Random.Range(110,140));break;  }  case 1:  {  diskdata.color = Color.red;  diskdata.speed = s + 10;  float RanX = UnityEngine.Random.Range(-1f, 1f) < 0 ? -1 : 1;  diskdata.Direction = new Vector3(RanX, 1, 0);diskdata.StartPoint = new Vector3(Random.Range(-130, -110), Random.Range(30, 80), Random.Range(110, 130));break;  }  case 2:  {  diskdata.color = Color.black;  diskdata.speed = s + 15;  float RanX = UnityEngine.Random.Range(-1f, 1f) < 0 ? -1 : 1;  diskdata.Direction = new Vector3(RanX, 1, 0);diskdata.StartPoint = new Vector3(Random.Range(-130,-110), Random.Range(30, 70), Random.Range(90, 120));break;  }case 3:{diskdata.color = Color.yellow;diskdata.speed = -s;float RanX = UnityEngine.Random.Range(-1f, 1f) < 0 ? -1 : 1;diskdata.Direction = new Vector3(RanX, 1, 0);diskdata.StartPoint = new Vector3(Random.Range(130, 110), Random.Range(30, 90), Random.Range(110, 140));break;}case 4:{diskdata.color = Color.red;diskdata.speed = -s - 10;float RanX = UnityEngine.Random.Range(-1f, 1f) < 0 ? -1 : 1;diskdata.Direction = new Vector3(RanX, 1, 0);diskdata.StartPoint = new Vector3(Random.Range(130, 110), Random.Range(30, 80), Random.Range(110, 130));break;}case 5:{diskdata.color = Color.black;diskdata.speed = -s - 15;float RanX = UnityEngine.Random.Range(-1f, 1f) < 0 ? -1 : 1;diskdata.Direction = new Vector3(RanX, 1, 0);diskdata.StartPoint = new Vector3(Random.Range(130, 110), Random.Range(30, 70), Random.Range(90, 120));break;}}used.Add(diskdata.GetInstanceID(), diskdata); //添加到使用中diskdata.name = diskdata.GetInstanceID().ToString();return diskdata;  }
}
  1. 上次已经写过了运动分离版的牧师与魔鬼了,这次可以将一部分运动分离的代码直接复用,主要的修改就是重写MoveToAction使Disk做类似有水平初速自由落体的运动(其实可以用刚体属性然后添加重力,此处我为了少修改代码而没有选择使用),然后重写一下具体在这个场景中的CCActionManager类。下面是重写的代码:

    • 重写的MoveToAction类:
        public class CCMoveToAction : SSAction{public float speedx;public float speedy = 0;private CCMoveToAction() { }public static CCMoveToAction getAction(float speedx){CCMoveToAction action = CreateInstance<CCMoveToAction>();action.speedx = speedx;return action;}public override void Update(){//模拟加速度为10的抛物线运动this.transform.position += new Vector3(speedx*Time.deltaTime, -speedy*Time.deltaTime+(float)-0.5*10*Time.deltaTime*Time.deltaTime,0);speedy += 10*Time.deltaTime;if (transform.position.y <= 1)//被点击和运动到地面都满足回收条件{destroy = true;CallBack.SSActionCallback(this);}}public override void Start(){}}
    • 重写的CCActionManager类:
        using Interfaces;public class CCActionManager : SSActionManager, SSActionCallback{int count = 0;//记录所有在移动的碟子的数量public SSActionEventType Complete = SSActionEventType.Completed;public void MoveDisk(Disk Disk){count++;Complete = SSActionEventType.Started;CCMoveToAction action = CCMoveToAction.getAction(Disk.speed);addAction(Disk.gameObject,action,this);}public void SSActionCallback(SSAction source) //运动事件结束后的回调函数{count--;Complete = SSActionEventType.Completed;source.gameObject.SetActive(false);}public bool IsAllFinished() //主要为了防止游戏结束时场景还有对象但是GUI按钮已经加载出来{if (count == 0) return true;else return false;}}
  2. 重写一下Interfaces,根据交互的需要定义函数。

        namespace Interfaces{public interface ISceneController{void LoadResources();}public interface UserAction{void Hit(Vector3 pos); // 发生点击事件,传送点击位置给场记void Restart();//重新开始游戏int GetScore();bool RoundStop();void RoundPlus();}public enum SSActionEventType : int { Started, Completed }public interface SSActionCallback{void SSActionCallback(SSAction source);}}
  3. 最后最重要的就是重写场记了,导演和之前还是一样的。

        using System.Collections;using System.Collections.Generic;using UnityEngine;using Interfaces;public class FirstSceneController : MonoBehaviour, ISceneController, UserAction{int score = 0;int round = 1;int tral = 0;bool start = false;CCActionManager Manager;DiskFactory DF;void Awake(){SSDirector director = SSDirector.getInstance();director.currentScenceController = this;DF = DiskFactory.DF;Manager = GetComponent<CCActionManager>();}// Use this for initializationvoid Start () {}// Update is called once per frameint count = 0;void Update () {if(start == true){count++;if (count >= 80){count = 0;if(DF == null){Debug.LogWarning("DF is NUll!");return;}tral++;Disk d = DF.GetDisk(round);Manager.MoveDisk(d);if (tral == 10){round++;tral = 0;}}}}public void LoadResources(){}public void Hit(Vector3 pos){Ray ray = Camera.main.ScreenPointToRay(pos);RaycastHit[] hits;hits = Physics.RaycastAll(ray);for (int i = 0; i < hits.Length; i++){RaycastHit hit = hits[i];if (hit.collider.gameObject.GetComponent<Disk>() != null){Color c = hit.collider.gameObject.GetComponent<Renderer>().material.color;if (c == Color.yellow) score += 1;if (c == Color.red) score += 2;if (c == Color.black) score += 3;hit.collider.gameObject.transform.position = new Vector3(0, -5, 0);}}}public int GetScore(){return score;}public void Restart(){score = 0;round = 1;start = true;}public bool RoundStop(){if (round > 3){start = false;return Manager.IsAllFinished();}else return false;}public int GetRound(){return round;}}
  4. 用户界面GUI,这次GUI还算简单,主要加了显示分数,时间,以及轮次的面板。
    public class InterfaceGUI : MonoBehaviour {UserAction UserActionController;public GameObject t;bool ss = false;float S;float Now;int round = 1;// Use this for initializationvoid Start () {UserActionController = SSDirector.getInstance().currentScenceController as UserAction;S = Time.time;}private void OnGUI(){if(!ss) S = Time.time;GUI.Label(new Rect(1000, 50, 500, 500),"Score: " + UserActionController.GetScore().ToString() + "  Time:  " + ((int)(Time.time - S)).ToString() + "  Round:  " + round );if (!ss && GUI.Button(new Rect(Screen.width / 2 - 30, Screen.height / 2 - 30, 100, 50), "Start")){S = Time.time;ss = true;UserActionController.Restart();}if (ss){round = UserActionController.GetRound();if (Input.GetButtonDown("Fire1")){Vector3 pos = Input.mousePosition;UserActionController.Hit(pos);}if (round > 3){round = 3;if (UserActionController.RoundStop()){ss = false;}}}}}

GItHUB传送门

Untiy3D - 3 打飞碟小游戏相关推荐

  1. 【游戏开发】unity教程4 打飞碟小游戏

    github传送门:https://github.com/dongzizhu/unity3DLearning/tree/master/hw4/Disk 视频传送门:https://space.bili ...

  2. ch05与游戏世界交互——鼠标打飞碟小游戏

    游戏内容要求: 游戏有 n 个 round,每个 round 都包括10 次 trial. 每个 trial 的飞碟的色彩.大小.发射位置.速度.角度.同时出现的个数都可能不同.它们由该 round ...

  3. 交互入门——基于鼠标控制的射击飞碟小游戏

    文章目录 游戏要求 游戏制作代码 用户交互接口 单例模板 飞碟工厂 动作相关类 飞碟飞行类: 飞行动作管理器 Controller场景控制器 裁判类 UI 游戏截图 游戏要求 游戏内容要求: 游戏有 ...

  4. Unity3D-打飞碟小游戏

    打飞碟(Hit UFO)游戏 要求 游戏规则 游戏实现 代码结构 导演类 飞碟工厂 场景控制类 动作管理类 UI实现 积分规则 游戏运行截图 参考资料 要求 游戏有 n 个 round,每个 roun ...

  5. 3d学习笔记(四)——打飞碟小游戏

    题目 编写一个简单的鼠标打飞碟(Hit UFO)游戏 游戏内容要求: 游戏有 n 个 round,每个 round 都包括10 次 trial: 每个 trial的飞碟的色彩.大小.发射位置.速度.角 ...

  6. Unity3D学习之路Homework4—— 飞碟射击游戏

    简单打飞碟小游戏 游戏规则与要求 规则 鼠标点击飞碟,即可获得分数,不同飞碟分数不一样,飞碟的初始位置与飞行速度随机,随着分数增加,游戏难度增加.初始时每个玩家都有6条生命,漏打飞碟扣除一条生命,直到 ...

  7. unity3d射箭模拟小游戏

    射箭小游戏制作过程 介绍 项目总览 注意 箭矢(Arrow) 箭矢跟随鼠标旋转 箭矢中靶的事件响应 箭矢碰撞处理 中靶计分 箭矢控制类(ArrowController) 箭矢回收 箭矢创建 箭矢运动 ...

  8. Unity3D学习笔记(6)—— 飞碟射击游戏

    游戏规则: 游戏分多个回合,每个回合有N个飞碟,玩家按空格后,321倒数3秒,飞碟飞出,点击鼠标,子弹飞出.飞碟落地或被击中,则准备下一次射击.每回合飞碟的大小.颜色.发射位置.发射角度.每次发射的数 ...

  9. ch06-物理系统与碰撞——Arrowshooting射箭小游戏

    游戏内容要求: 1.靶对象为 5 环,按环计分: 2.箭对象,射中后要插在靶上 增强要求:射中后,箭对象产生颤抖效果,到下一次射击 或 1秒以后 3.游戏仅一轮,无限 trials: 增强要求:添加一 ...

  10. 小学计算机一个游戏梦游,梦游先生小游戏合集(上部)

    梦游先生小游戏合集包含了目前网络上流行的梦游先生系列的1到4部. 梦游先生是热门的冒险解谜类游戏,梦游先生1到4部,支持离线玩. 梦游先生1-疯狂都市 经典的华纳冒险系列之梦游先生操作简单,但是情节, ...

最新文章

  1. torch分布式训练学习笔记
  2. BUUCTF(pwn)ciscn_2019_ne_5
  3. Oracle的AWR报告分析
  4. IReport报表分组与分组统计
  5. 火狐浏览器插件HTTPFOX抓传输数据
  6. codeforces 136A-C语言解题报告
  7. C++基础13-类和对象之继承2
  8. atitit. applet 浏览器插件 控件 的环境,开发,提示总结o9o
  9. html/jsp下载Excel文件
  10. 无法在此设备上查看受保护内容_细说丨你想要的Excel保护与加密都在这里
  11. 找出所有子集的异或总和再求和
  12. linux gcc下实现简单socket套接字小程序
  13. kitti pkl可视化,KITTI数据集格式说明
  14. 如鹏网.Net基础1 随机数“骗局”揭秘
  15. Java 生成数字证书系列(四)生成数字证书(续)
  16. 一款灵活可配置的开源监控平台
  17. 学计算机用商务本还是游戏本,工作学习游戏?这 8 款最具性价比的笔记本电脑,总有一款适合你...
  18. python数据分析期末_Python数据分析期末作业
  19. 浅谈人机混合智能——计算-算计模型
  20. Locust系列-Locust入门

热门文章

  1. 分镜头剧本模板、故事图模板
  2. 周记20180309
  3. 软件工程-第三章-需求分析
  4. 转载:Latex——在线快速生成表格代码
  5. JAVA验证身份证号码校验码是否正确
  6. java验证身份证号码的合格性
  7. 【信号与系统实验】实验四 傅里叶变换、系统的频域分析
  8. 两款WiFi无线网络扫描工具软件 WirelessMon Xirrus WiFi Inspector
  9. 为Macbook添加自己喜欢的英汉辞典
  10. 基于大数据技术的全国高速公路通行数据 动态监测平台建设