# unity_disk **Repository Path**: lyouuuuu/unity_disk ## Basic Information - **Project Name**: unity_disk - **Description**: unity disk小游戏 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-11-21 - **Last Updated**: 2023-01-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Unity Disk ## 演示 动图: ![show](image/README/show.gif) 每轮有10次Trial,每次Trial随机射出多个飞碟,飞碟会朝着一个方向边旋转边前进,飞碟的初始位置、朝向、角度、转动方向和颜色随机;左上角显示当前轮数和分数: ![1669053340874](image/README/1669053340874.png) 一轮结束后,弹出提示,并开始倒计时: ![1669053289402](image/README/1669053289402.png) 随着轮数的提高,飞碟数量和速度都会有所提高,加大难度,同时点中一个飞碟的得分也会提高: ![1669053463804](image/README/1669053463804.png) 游戏结束后,左上角展示得分,并可以点击屏幕中央按钮重新开始游戏: ![1669053711331](image/README/1669053711331.png) ## 实现 创建三种颜色飞碟的预制 ![1669052383050](image/README/1669052383050.png) 给camera添加天空盒 ![1669052432748](image/README/1669052432748.png) 使用单例设计模式编写带有缓冲的飞碟工厂 ```C# using System.Collections; using System.Collections.Generic; using UnityEngine; public class DiskFactory { protected static DiskFactory instance; Queue freelist = new Queue(); RoundController controller; public static DiskFactory Instance() { if (instance == null) { instance = new DiskFactory(); } return instance; } public void SetController(RoundController controller) { this.controller = controller; } // 获取飞碟 public Disk GetDisk() { if (freelist.Count == 0) { // 如果freelist中没有剩余的飞碟则创建10个 for (int i = 0; i < 10; i++) { GameObject obj = null; switch (Random.Range(0, 4)) { case 0: obj = Object.Instantiate(Resources.Load("Prefabs/red_disk")); break; case 1: obj = Object.Instantiate(Resources.Load("Prefabs/green_disk")); break; default: obj = Object.Instantiate(Resources.Load("Prefabs/blue_disk")); break; } Disk disk = new Disk(obj); disk.DisActive(); ClickDisk click = obj.AddComponent(typeof(ClickDisk)) as ClickDisk; click.disk = disk; click.controller = controller; freelist.Enqueue(disk); } } Disk d = freelist.Dequeue(); d.Active(); return d; } // 释放飞碟 public void FreeDisk(Disk disk) { disk.DisActive(); freelist.Enqueue(disk); } } ``` 飞碟类 ```C# public class Disk { public GameObject obj; public Vector3 end; // 终点 public float speed; // 移动速度 public float rSpeed = 1; // 旋转速度 public bool died = false; public Vector3 r; // 旋转角度 public Disk(GameObject obj) { this.obj = obj; } public void Init(Vector3 beg, Vector3 end, float speed, Quaternion q, Vector3 r) { this.obj.transform.position = beg; this.end = end; this.speed = speed; this.obj.transform.rotation = q; this.r = r; } public void Active() { this.died = false; this.obj.SetActive(true); } public void DisActive() { this.died = true; this.obj.SetActive(false); } public void Move() { if (died) return; Vector3 deta = end - this.obj.transform.position; Vector3 mv = deta.normalized * speed * Time.deltaTime; obj.transform.Rotate(r * Time.deltaTime * rSpeed); if (deta.magnitude < mv.magnitude) { this.died = true; } else { obj.transform.position = obj.transform.position + mv; } } } ``` 控制器类,控制游戏流程 ```C# public class RoundController : MonoBehaviour { ArrayList list = new ArrayList(); // Start is called before the first frame update void Start() { DiskFactory.Instance().SetController(this); UI ui = this.gameObject.AddComponent(typeof(UI)) as UI; ui.controller = this; } public float time = 0; // 下一轮开始时间 public int n = 0; public bool end = false; public int goal = 0; int t = 0; float trial_time = 0; public void Restart() { goal = 0; n = 0; time = 0; end = false; } public void AddGoal() { this.goal++; } // Update is called once per frame void Update() { if (end) return; if (trial_time > 0) // 等待1秒后下一个trial { trial_time -= Time.deltaTime; if(trial_time <= 0) { Debug.Log("new trial"); Trial(n); } else { return; } } if(time > 0) // 等待3秒后下一轮 { time -= Time.deltaTime; if(time <= 0) { t = 10; } else { return; } } bool all_died = true; foreach (Disk x in list) { if (x.died) { continue; } x.Move(); all_died = false; } if (all_died) // 全部飞碟被击落或飞走后 { foreach (Disk x in list) // 回收所有飞碟 { DiskFactory.Instance().FreeDisk(x); } list.Clear(); if (t > 0) // 还有剩余的trial { t--; trial_time = 1; } else // 准备开始下一轮 { time = 3; n++; if (n > 10) { end = true; } } } } // 根据轮数随机生成每个trial的飞碟数 int genDiskCount(int n) { int min, max; if (n >= 9) { min = 3; max = 10; } else if (n >= 7) { min = 2; max = 5; } else if (n >= 5) { min = 1; max = 3; } else if(n >= 2) { min = 1; max = 2; } else { min = max = 1; } return Random.Range(min, max+1); } // 根据轮数生成飞碟速度 float genSpeed(int n) { if (n >= 8) { return Random.Range(14.0f, 30.0f); } else if (n >= 5) { return Random.Range(12.0f, 30.0f); } else { return Random.Range(12.0f, 22.0f); } } // 随机生成飞碟起始位置 Vector3 GenBegin() { // return new Vector3(0, 0, 0); return new Vector3(12.7299995f, Random.Range(-3.9f, 4.5f), 8.83201981f); } // 随机生成飞碟终点位置 Vector3 GenEnd() { return new Vector3(-13.96f, Random.Range(-3.9f, 4.5f), 8.83201981f); } // 随机生成初始角度和旋转角度 Vector3 GenEuler() { return new Vector3(Random.Range(-180f,180f), Random.Range(-180f, 180f), Random.Range(-180f, 180f)); } // 随机生成旋转速度 float GenRSpeed() { return Random.Range(0.0f, 2.0f); } // 开始一次trial void Trial(int n) { int c = genDiskCount(n); for(int i = 0; i 0) { GUI.Label(new Rect(Screen.width / 2 - 130, Screen.height / 2 - 35, 260, 70), String.Format("第{0}轮将在{1}秒后开始", controller.n, Math.Ceiling(controller.time)), labelStyle); } GUI.Label(new Rect(10, 0, 260, 70), String.Format("轮数:{0} 分数:{1}", controller.n, controller.goal), labelStyle); } } ``` ## 可选的抛物线运动形式 ```C# using System.Collections; using System.Collections.Generic; using UnityEngine; abstract public class DiskMoving : MonoBehaviour { public Disk disk; void Update() { if(!disk.died) move(); } abstract protected void move(); } // 直线运动 public class LinearDiskMoving : DiskMoving { protected override void move() { Vector3 deta = disk.end - disk.obj.transform.position; Vector3 mv = deta.normalized * disk.speed * Time.deltaTime; disk.obj.transform.Rotate(disk.r * Time.deltaTime * disk.rSpeed); if (deta.magnitude < mv.magnitude) { disk.died = true; } else { disk.obj.transform.position = disk.obj.transform.position + mv; } } } // 添加刚体组件,抛物运动 public class ParabolicDiskMoving: DiskMoving { public Rigidbody rigid; protected override void move() { if(disk.obj.transform.position.x < -13.96f) { disk.died = true; } } private void FixedUpdate() { //rigid.AddForce(new Vector3(0, -10f, 0)); } void Start() { rigid = disk.obj.AddComponent(); rigid.velocity = (disk.end - disk.beg).normalized * disk.speed; rigid.angularVelocity = disk.r * disk.rSpeed; rigid.useGravity = true; } } ``` 在DiskFatory中修改: ```C# // DiskMoving moving = obj.AddComponent(typeof(LinearDiskMoving)) as DiskMoving; DiskMoving moving = obj.AddComponent(typeof(ParabolicDiskMoving)) as DiskMoving; moving.disk = disk; ``` 即可实现更改为刚体抛物运动