上一个做的飞碟游戏虽然是功能也齐全,但是我感觉架构不是很好有点紊乱,不利于后期维护以及改进,所以我按照一个完整的架构重新做了一次,思路更清晰,而且还添加了更多的功能。这次的飞碟游戏是两个关卡,50分上第二关,100分通第二关,而且可以任意切换模式(运动学非刚体模式和物理刚体模式,前者没有刚体组件,后者加刚体组件)
讲讲规则先:一开始就是第一关,默认模式为运动学非刚体模式,还是按空格发射飞碟(一次一个),一个发射期间不能发射第二个,一个飞碟如果没打中会在一定时间内消失,飞碟消失才能发射下一个飞碟,鼠标左键射击子弹,按数字键2切换模式为物理刚体模式,按数字键1切换到运动学非刚体模式。
上个效果图(由于比较难射中,所以我把飞碟大小弄大一些,分数显示被遮住了):
接下来讲一下设计思路,游戏架构如下
DiskModule类挂在飞碟预设上,用来处理触发器事件(飞碟碰到子弹或者地板时触发)
DiskFactory类专门生产飞碟,所有生产飞碟的细节都在这里实现,会根据每个关卡生产不同大小以及颜色的飞碟,并且回收飞碟以便再次加以利用
Recorder类只负责记录分数或者重置分数
Userface类处理用户界面逻辑
CCActionManager类实现运动学的动作,比如运动学非刚体的飞碟发射
PhysicsActionManager类实现物理刚体学动作,比如子弹的发射以及刚体飞碟的发射
SceneController类加载场景以及调用各个其他类来实现功能,比如Userface调用子弹或者飞碟射击要通过SceneController根据不同模式以及关卡来调用相应的动作管理器
具体代码如下,(注释已经把代码思想写的很清楚):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Director : System.Object
{
private static Director _instance;
public SceneController _Controller { get; set; }
public static Director getinstance()
{
if (_instance == null)
{
_instance = new Director();
}
return _instance;
}
public int getFPS()
{
return Application.targetFrameRate;
}
public void setFPS(int fps)
{
Application.targetFrameRate = fps;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Userface : MonoBehaviour {
private SceneController _Controller;
public Camera _camera;
public Text Score;//显示分数
public Text Round;//显示关卡
public Text Mode;//显示模式
void Start () {
_Controller = (SceneController)FindObjectOfType(typeof(SceneController));
}
// Update is called once per frame
void Update () {
if(Input.GetKeyDown("1"))//按下1切换到运动学模式
{
if(!_Controller.isFlying)
{
Debug.Log("NonPhy mode");
_Controller._mode = false;
}
}
if(Input.GetKeyDown("2"))//按下2切换到物理刚体模式
{
if (!_Controller.isFlying)
{
Debug.Log("Phy mode");
_Controller._mode = true;
}
}
if(Input.GetKeyDown("space"))//按下空格发射飞碟
{
_Controller.ShootDisk();
}
if (Input.GetMouseButtonDown(0)&&!_Controller.isShooting)//按下左键发射子弹
{
Ray mouseRay = _camera.ScreenPointToRay(Input.mousePosition);
_Controller.ShootBullet(mouseRay.direction);
}
Score.text = "Score:" + _Controller.getRecorder().getScore();
Round.text = "Round:" + _Controller.getRound();
if (_Controller._mode == false) Mode.text = "Mode:CCAction";
else Mode.text = "Mode:PhysicsAction";
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Recorder : MonoBehaviour {
private int _score = 0;
public void AddScore(string name)//根据碰撞物名称加减分
{
if (name == "Plane") _score -= 10;
else if (name == "bullet(Clone)") _score += 10;
}
public int getScore()
{
return _score;
}
public void reset()
{
_score = 0;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DiskFactory : MonoBehaviour {
public List<GameObject> Using; //储存正在使用的
public List<GameObject> Used; //储存空闲的
private SceneController _Controller;
public GameObject DiskPrefab;
void Start () {
Using = new List<GameObject>();
Used = new List<GameObject>();
_Controller = (SceneController)FindObjectOfType(typeof(SceneController));
}
public GameObject getDisk(bool isPhy,int _Round)
{
GameObject t;
if (Used.Count == 0)
{
t = GameObject.Instantiate(DiskPrefab) as GameObject;
}
else
{
t = Used[0];
Used.Remove(t);
}
t.GetComponent<MeshCollider>().isTrigger = true;
t.SetActive(true);
if (isPhy)//物理学模式加刚体组件
{
if (t.GetComponent<Rigidbody>() == null)
t.AddComponent<Rigidbody>();
}
else if (!isPhy)//运动学模式去除刚体组件
{
if (t.GetComponent<Rigidbody>())
Destroy(t.GetComponent<Rigidbody>());
}
Using.Add(t);
if(_Round==1)//第一关的飞碟形式
{
t.transform.localScale *= 2;
t.GetComponent<Renderer>().material.color = Color.green;
}//第二关为初始大小以及红色
return t;
}
private void freeDisk(int round)//把场景中inactive的飞碟回收
{
for (int i = 0; i < Using.Count; i++)
{
GameObject t = Using[i];
if (!t.activeInHierarchy)
{
Using.RemoveAt(i);
Used.Add(t);
Destroy(t.GetComponent<Rigidbody>());
if (round==1)
t.transform.localScale /= 2;
t.GetComponent<Renderer>().material.color = Color.red;
}
}
}
void Update () {
freeDisk(_Controller.getRound());
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DiskModule : MonoBehaviour {
private string _sth = "";
private float _time = 8f;
private SceneController _Controller;
void Start () {
_Controller = (SceneController)FindObjectOfType(typeof(SceneController));
}
void OnTriggerEnter(Collider other)//触发器事件
{
if(_sth=="")
{
_sth = other.gameObject.name;
Debug.Log(_sth);
if (_sth == "bullet(Clone)")
{
this._time = 0;//直接回收
_Controller._explosion.GetComponent<Renderer>().material.color = this.GetComponent<Renderer>().material.color;
_Controller._explosion.transform.position = this.transform.position;
_Controller._explosion.Play();//播放爆炸粒子
}
_Controller.getRecorder().AddScore(_sth);
_Controller.isShooting = false;
}
}
void Update () {
if (_Controller.isFlying)
{
if (_time > 0) _time -= Time.deltaTime;
else if (_time <= 0)//回收飞碟
{
GetComponent<MeshCollider>().isTrigger = false;
this.gameObject.SetActive(false);
_time = 8f;
_sth = "";
_Controller.isFlying = false;
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SceneController : MonoBehaviour {
private CCActionManager _CCAM;
private PhysicsActionManager _PhyAM;
private DiskFactory _Factory;
private Recorder _Recorder;
private int _Round = 1;
public GameObject _bullet;//子弹
public ParticleSystem _explosion;//爆炸粒子
public bool _mode = false;//标记模式
public bool isShooting = false;//判断子弹是否正在飞
public bool isFlying = false;//判断飞碟是否正在飞
private float _time = 1f;
void Start () {
_bullet = GameObject.Instantiate(_bullet) as GameObject;
_explosion = GameObject.Instantiate(_explosion) as ParticleSystem;
Director _director = Director.getinstance();
_director._Controller = this;
_CCAM = (CCActionManager)FindObjectOfType(typeof(CCActionManager));
_PhyAM = (PhysicsActionManager)FindObjectOfType(typeof(PhysicsActionManager));
_Recorder = (Recorder)FindObjectOfType(typeof(Recorder));
_Factory = (DiskFactory)FindObjectOfType(typeof(DiskFactory));
_director.setFPS(60);
_director._Controller = this;
}
public DiskFactory getFactory()
{
return _Factory;
}
public int getRound()
{
return _Round;
}
public Recorder getRecorder()
{
return _Recorder;
}
public CCActionManager getCCActionManager()
{
return _CCAM;
}
public PhysicsActionManager getPhysicsActionManager()
{
return _PhyAM;
}
public void ShootDisk()
{
if(!isFlying)
{
GameObject _disk = _Factory.getDisk(_mode, _Round);//根据不同关卡以及不同模式生产不同的飞碟
if (!_mode) _CCAM.ShootDisks(_disk);//根据不同模式调用不同动作管理器的动作函数
else _PhyAM.ShootDisks(_disk);
isFlying = true;
}
}
public void ShootBullet(Vector3 _dir)//调用动作管理器的射击子弹函数
{
isShooting = true;
_PhyAM.ShootBullets(_bullet, _dir);
}
private void AddRound()//判断是否通关
{
if (_Recorder.getScore() >= 50&&_Round == 1)
{
_Round++;
}
else if (_Recorder.getScore() > 100&& _Round == 2)
{
_Round = 1;
_Recorder.reset();
}
}
void Update () {
AddRound();
if(isShooting)
{
if(_time>0)
{
_time -= Time.deltaTime;
if(_time<=0)
{
isShooting = false;
_time = 1f;
}
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PhysicsActionManager : MonoBehaviour {
private SceneController _Controller;
void Start () {
_Controller = (SceneController)FindObjectOfType(typeof(SceneController));
}
public void ShootBullets(GameObject _bullet, Vector3 _dir)//发射子弹
{
_bullet.transform.position = new Vector3(0, 2, 0);
_bullet.GetComponent<Rigidbody>().velocity = Vector3.zero; // 子弹刚体速度重置
_bullet.GetComponent<Rigidbody>().AddForce(_dir * 500f, ForceMode.Impulse);
}
public void ShootDisks(GameObject _disk)//发射飞碟
{
_disk.transform.position = new Vector3(0, 2, 2);
float _dx = Random.Range(-20f, 20f);
Vector3 _dir = new Vector3(_dx, 30, 20);
_disk.transform.up = _dir;
if (_Controller.getRound() == 1)
{
_disk.GetComponent<Rigidbody>().AddForce(_dir*20f, ForceMode.Force);
} else if(_Controller.getRound() == 2)
{
_disk.GetComponent<Rigidbody>().AddForce(_dir*30f, ForceMode.Force);
}
}
void Update () {
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CCActionManager : MonoBehaviour {
private SceneController _Controller;
private GameObject temp;
void Start () {
_Controller = (SceneController)FindObjectOfType(typeof(SceneController));
}
public void ShootDisks(GameObject _disk)//发射飞碟
{
_disk.transform.position = new Vector3(Random.Range(-1f, 1f), 2f, 2f);
temp = _disk;
}
void Update () {
if(_Controller.isFlying&&!_Controller._mode)
{
if (_Controller.getRound() == 1)
{
temp.transform.position = Vector3.MoveTowards(temp.transform.position, new Vector3(0, 2, 100), 0.1f);
}
else if (_Controller.getRound() == 2)
{
temp.transform.position = Vector3.MoveTowards(temp.transform.position, new Vector3(0, 2, 100), 0.2f);
}
}
}
}