Unity3D学习:飞碟游戏进化版

上一个做的飞碟游戏虽然是功能也齐全,但是我感觉架构不是很好有点紊乱,不利于后期维护以及改进,所以我按照一个完整的架构重新做了一次,思路更清晰,而且还添加了更多的功能。这次的飞碟游戏是两个关卡,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);
            }
        }
    }
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值