# 射飞碟游戏 #
### 具体要求如下: ###
假设有一支枪在摄像机位置(0,1,-10),在(0,0,0-10-20)放置三个小球作为距离标记,调整视角直到小球在下中部
将鼠标所在平面坐标,转换为子弹(球体)射出的角度方向。子弹使用物理引擎,初速度恒定。(U3d 坐标变换: http://www.cnblogs.com/tekkaman/p/3809409.html )
`Vector3 mp = Input.mousePosition; //get Screen Position
print (mp.ToString());
Vector3 mp1 = cam.camera.ScreenToViewportPoint (mp);
mp1.z = 10; //距摄像头 10 位置立面
mp1 = cam.camera.ViewportToWorldPoint (mp1);
print (mp1.ToString());`
游戏要分多个 round , 飞碟数量每个 round 都是 n 个,但色彩,大小;发射位置,速度,角度,每次发射数量按预定规则变化。
用户按空格后,321倒数3秒,飞碟飞出(物理引擎控制),点击鼠标,子弹飞出。飞碟落地,或被击中,则准备下一次射击。
以下是一些技术要求:
子弹仅需要一个,不用时处于 deactive 状态
飞碟用一个带缓存的工厂生产,template 中放置预制的飞碟对象
程序类图设计大致如下:![](http://ss.sysu.edu.cn/~pml/se347/_images/HitDisk_2.png)
下面是游戏的组件代码:
###1、GameModel.cs###
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Com.Mygame;
public class GameModel : MonoBehaviour {
public float countDown = 3f;
public float timeToEmit;
private bool counting;
private bool shooting;
public bool isCounting() {
return counting;
}
public bool isShooting() {
return shooting;
}
private List<GameObject> disks = new List<GameObject>(); // 飞碟对象列表
private List<int> diskIds = new List<int>();
private int diskScale;
private Color diskColor;
private Vector3 emitPosition;
private Vector3 emitDirection;
private float emitSpeed;
private int emitNumber;
private bool emitEnable;
private SceneController scene;
void Awake() {
scene = SceneController.getInstance();
scene.setGameModel(this);
}
public void setting(int scale, Color color, Vector3 emitPos, Vector3 emitDir, float speed, int num) { // 场景设置
diskScale = scale; // 没什么好说的,赋值
diskColor = color;
emitPosition = emitPos;
emitDirection = emitDir;
emitSpeed = speed;
emitNumber = num;
}
// 准备下一次发射
public void prepareToEmitDisk() {
if (counting == false && shooting == false) {
timeToEmit = countDown;
emitEnable = true; // 可发射变为真
}
}
// 发射飞碟
void emitDisks() {
for (int i = 0; i < emitNumber; ++i) {
diskIds.Add(Factory.getInstance().getDisk());
disks.Add(Factory.getInstance().getDiskObject(diskIds[i]));
disks[i].transform.localScale *= diskScale;
disks[i].transform.position = new Vector3(emitPosition.x, emitPosition.y + i, emitPosition.z);
disks[i].SetActive(true);
disks[i].rigidbody.AddForce(emitDirection * Random.Range(emitSpeed * 5, emitSpeed * 10) / 10, ForceMode.Impulse);
}
}
// 回收
void freeADisk(int i) {
Factory.getInstance().free(diskIds[i]);
disks.RemoveAt(i);
diskIds.RemoveAt(i);
}
void FixedUpdate() {
if (timeToEmit > 0) {
counting = true;
timeToEmit -= Time.deltaTime;
} else {
counting = false;
if (emitEnable == true) {
emitDisks();
emitEnable = false; // 改变之后可发射变为假
shooting = true;
}
}
}
void Update() {
for (int i = 0; i < disks.Count; i++) {
if (!disks[i].activeInHierarchy) {
scene.getJudge().scoreADisk();
freeADisk(i);
} else if (disks[i].transform.position.y < 0) {
scene.getJudge().failADisk();
freeADisk(i);
}
}
if (disks.Count == 0) { // 如果不存在飞碟了,停止射击
shooting = false;
}
}
}
这个文件控制的是游戏场景,通过调用Factory.getInstance()功能来获取飞碟的实例,当飞碟被击中或者自己落地的时候,将被freeDisk()函数回收,并且通过调用Judge类中的函数,来决定分数的获得和扣除,并以此来决定是否结束游戏或者进入下一关卡。FixedUpdate()和Update()函数通过bool条件判断,来决定是否可以继续射击。
###2、UserInterface###
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using Com.Mygame;
public class UserInterface : MonoBehaviour {
public Text mainText;
public Text scoreText;
public Text roundText;
private int round; // 判定当前回合
public GameObject bullet;
public ParticleSystem explosion;
public float fireRate = .25f;
public float speed = 500f;
private float nextFireTime;
private IUserInterface userInt;
private IQueryStatus queryInt;
void Start() { // 游戏开始,加载
bullet = GameObject.Instantiate(bullet) as GameObject;
explosion = GameObject.Instantiate(explosion) as ParticleSystem;
userInt = SceneController.getInstance() as IUserInterface;
queryInt = SceneController.getInstance() as IQueryStatus;
}
void Update() {
if (queryInt.isCounting()) {
mainText.text = ((int)queryInt.getEmitTime()).ToString();
} else {
if (Input.GetKeyDown("space")) { // 输入空格开始
yield return new WaitforSeconds(3f); // 倒数3秒后开始
userInt.emitDisk();
}
if (queryInt.isShooting()) {
mainText.text = ""; // 隐藏maintext
}
// 发射子弹
if (queryInt.isShooting() && Input.GetMouseButtonDown(0) && Time.time > nextFireTime) {
nextFireTime = Time.time + fireRate; // 开火冷却时间
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
bullet.rigidbody.velocity = Vector3.zero; // 重置子弹速度
bullet.transform.position = transform.position; // 子弹射出
bullet.rigidbody.AddForce(ray.direction * speed, ForceMode.Impulse);
RaycastHit hit;
if (Physics.Raycast(ray, out hit) && hit.collider.gameObject.tag == "Disk") {
explosion.transform.position = hit.collider.gameObject.transform.position;
explosion.Play();
// 击中飞碟自动回收
hit.collider.gameObject.SetActive(false);
}
}
}
roundText.text = "Round: " + queryInt.getRound().ToString();
scoreText.text = "Score: " + queryInt.getPoint().ToString();
if (round != queryInt.getRound()) {
round = queryInt.getRound();
mainText.text = "Round " + round.ToString() + " Start";
}
}
}
该文件创建用户界面,其中包含着加载、提示、游戏主体等部分。作业要求中,用户按空格后,321倒数3秒,飞碟飞出(物理引擎控制),点击鼠标左键,子弹飞出。飞碟落地,或被击中,则准备下一次射击。我用了waitforSeconds函数来实现,在等待3秒之后,开始飞出飞碟,飞碟落地或被击中的函数已经在GameModel.cs文件中写出,这里就不再赘述。值得一提的是,刚开始我测试游戏的时候,子弹的速度会越来越快,这是因为我没有将其清零的缘故,后来我令其velocity赋值为0来进行清零。上一次的作业中我的子弹使用的是射线判定,这次则用的是有碰撞体积的物理引擎,这点可以在装载之后发现。
###3、SceneController.cs###
using UnityEngine;
using System.Collections;
using Com.Mygame;
namespace Com.Mygame {
public interface IUserInterface { // 场景控制器,是游戏中十分重要的一个环节
void emitDisk();
}
public interface IQueryStatus { // 记录回合和得分
bool isCounting();
bool isShooting();
int getRound();
int getPoint();
int getEmitTime();
}
public interface IJudgeEvent {
void nextRound();
void setPoint(int point);
}
public class SceneController : System.Object, IQueryStatus, IUserInterface, IJudgeEvent { // 继承各类
private static SceneController _instance;
private SceneControllerBC _baseCode; // 分别为SceneControllerBC、GameModel、Judege
private GameModel _gameModel;
private Judge _judge;
private int _round;
private int _point;
public static SceneController getInstance() {
if (_instance == null) {
_instance = new SceneController(); // 返回SceneController的实例
}
return _instance;
}
public void setGameModel(GameModel obj) {
_gameModel = obj;
}
internal GameModel getGameModel() {
return _gameModel;
}
public void setJudge(Judge obj) {
_judge = obj;
}
internal Judge getJudge() {
return _judge;
}
public void setSceneControllerBC(SceneControllerBC obj) {
_baseCode = obj;
}
internal SceneControllerBC getSceneControllerBC() {
return _baseCode;
}
public void emitDisk() {
_gameModel.prepareToEmitDisk();
}
public bool isCounting() {
return _gameModel.isCounting();
}
public bool isShooting() {
return _gameModel.isShooting();
}
public int getRound() {
return _round;
}
public int getPoint() {
return _point;
}
public int getEmitTime() {
int result = (int)_gameModel.timeToEmit + 1;
return result;
}
public void setPoint(int point) {
_point = point;
}
public void nextRound() {
_point = 0; _baseCode.loadRoundData(++_round);
}
}
}
场景控制器,实现各种成员变量的返回实现,以及接口定义和保存注入对象。其中它有两个私有变量round和point,分别记录游戏正在进行的回合,以及玩家目前的得分,应用在GameModel中实现。
###4、SceneControllerBC.cs###
UnityEngine;
using System.Collections;
using Com.Mygame;
public class SceneControllerBC : MonoBehaviour {
private Color color;
private Vector3 emitPos;
private Vector3 emitDir;
private float speed;
void Awake() {
SceneController.getInstance().setSceneControllerBC(this);
}
public void loadRoundData(int round) { // 关卡的设计
switch (round) {
case 1: // 第一关
color = Color.green;
emitPos = new Vector3(-2.5f, 0.2f, -5f); // 初始条件
emitDir = new Vector3(24.5f, 40.0f, 67f);
speed = 4;
SceneController.getInstance().getGameModel().setting(1, color, emitPos, emitDir.normalized, speed, 1);
break;
case 2: // 第二关
color = Color.red;
emitPos = new Vector3(2.5f, 0.2f, -5f);
emitDir = new Vector3(-24.5f, 35.0f, 67f);
speed = 4;
SceneController.getInstance().getGameModel().setting(1, color, emitPos, emitDir.normalized, speed, 2); // 设定条件
break;
case 3: // 第三关
color = Color.red;
emitPos = new Vector3(2.5f, 0.2f, -5f);
emitDir = new Vector3(-24.5f, 35.0f, 67f); // 飞碟初始位置不变,仅改变速度
speed = 5;
SceneController.getInstance().getGameModel().setting(1, color, emitPos, emitDir.normalized, speed, 4); // 其实改一下飞碟的速度就可以了
break;
}
}
}
此文件为关卡类的定义,我只做了3个关卡,题目要求我:游戏要分多个 round , 飞碟数量每个 round 都是 n 个,但色彩,大小;发射位置,速度,角度,每次发射数量按预定规则变化。因此我没有改变飞碟的数量,位置和角度,从速度入手,越到后面的关卡越快。函数Awake()用来获取场景控制器实例,loadRoundData()用来初始化游戏场景,即定义飞碟的属性。
###5、Factory.cs###
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Com.Mygame;
namespace Com.Mygame {
public class Factory : System.Object {
private static Factory _instance; // 获取实例
private static List<GameObject> diskList;
public GameObject diskTemplate;
public static Factory getInstance() { // 工厂实例
if (_instance == null) {
_instance = new Factory();
diskList = new List<GameObject>();
}
return _instance;
}
public int getDisk() {
for (int i = 0; i < diskList.Count; i++) {
if (!diskList[i].activeInHierarchy) { // 判断是否飞碟空闲
return i;
}
}
diskList.Add(GameObject.Instantiate(diskTemplate) as GameObject); // 设置新的飞碟
return diskList.Count-1;
}
public void free(int id) {
if (id >= 0 && id < diskList.Count) { // 判断是否有效
diskList[id].rigidbody.velocity = Vector3.zero; // 速度清零
diskList[id].transform.localScale = diskTemplate.transform.localScale;
diskList[id].SetActive(false); // 活动能力重置
}
}
public GameObject getDiskObject(int id) {
if (id > -1 && id < diskList.Count) {
return diskList[id];
}
return null;
}
}
}
public class DiskFactoryBC : MonoBehaviour { // 另一个类BC
public GameObject disk;
void Awake() {
Factory.getInstance().diskTemplate = disk; // 用于获取飞碟实例
}
}
题目要求:飞碟用一个带缓存的工厂生产,template 中放置预制的飞碟对象。这个就是飞碟工厂,管理飞碟实例,同时对外屏蔽飞碟实例的的提取和回收细节。它定义了获取、回收飞碟的功能,并且由于是public函数,可以被其他函数直接调用,来管理、应用飞碟。
###6、Judge.cs###
using UnityEngine;
using System.Collections;
using Com.Mygame;
public class Judge : MonoBehaviour { // 判定得分失分,能否进入下一回合
public int oneDiskScore = 10;
public int oneDiskFail = 10;
public int disksToWin = 4;
private SceneController scene;
void Awake() {
scene = SceneController.getInstance();
scene.setJudge(this); // 设定规则
}
void Start() {
scene.nextRound(); // 第一关
}
public void scoreADisk() // 得分
{
scene.setPoint(scene.getPoint() + oneDiskScore);
if (scene.getPoint() == disksToWin * oneDiskScore) {
scene.nextRound();
}
}
public void failADisk() { // 失分
scene.setPoint(scene.getPoint() - oneDiskFail); // 判定条件,飞碟掉落
}
}
用以判断得失分的类,当符合得分条件时,调用得分函数;当符合失分条件时(即飞碟未击中而掉落时),调用失分函数。当得分符合条件时,进入下一回合。
*题目条件:有一支枪在摄像机位置(0,1,-10),在(0,0,0-10-20)放置三个小球作为距离标记,调整视角直到小球在下中部。*
部件设定:
摄像机:# 射飞碟游戏 #
### 具体要求如下: ###
假设有一支枪在摄像机位置(0,1,-10),在(0,0,0-10-20)放置三个小球作为距离标记,调整视角直到小球在下中部
将鼠标所在平面坐标,转换为子弹(球体)射出的角度方向。子弹使用物理引擎,初速度恒定。(U3d 坐标变换: http://www.cnblogs.com/tekkaman/p/3809409.html )
`Vector3 mp = Input.mousePosition; //get Screen Position
print (mp.ToString());
Vector3 mp1 = cam.camera.ScreenToViewportPoint (mp);
mp1.z = 10; //距摄像头 10 位置立面
mp1 = cam.camera.ViewportToWorldPoint (mp1);
print (mp1.ToString());`
游戏要分多个 round , 飞碟数量每个 round 都是 n 个,但色彩,大小;发射位置,速度,角度,每次发射数量按预定规则变化。
用户按空格后,321倒数3秒,飞碟飞出(物理引擎控制),点击鼠标,子弹飞出。飞碟落地,或被击中,则准备下一次射击。
以下是一些技术要求:
子弹仅需要一个,不用时处于 deactive 状态
飞碟用一个带缓存的工厂生产,template 中放置预制的飞碟对象
程序类图设计大致如下:![](http://ss.sysu.edu.cn/~pml/se347/_images/HitDisk_2.png)
下面是游戏的组件代码:
###1、GameModel.cs###
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Com.Mygame;
public class GameModel : MonoBehaviour {
public float countDown = 3f;
public float timeToEmit;
private bool counting;
private bool shooting;
public bool isCounting() {
return counting;
}
public bool isShooting() {
return shooting;
}
private List<GameObject> disks = new List<GameObject>(); // 飞碟对象列表
private List<int> diskIds = new List<int>();
private int diskScale;
private Color diskColor;
private Vector3 emitPosition;
private Vector3 emitDirection;
private float emitSpeed;
private int emitNumber;
private bool emitEnable;
private SceneController scene;
void Awake() {
scene = SceneController.getInstance();
scene.setGameModel(this);
}
public void setting(int scale, Color color, Vector3 emitPos, Vector3 emitDir, float speed, int num) { // 场景设置
diskScale = scale; // 没什么好说的,赋值
diskColor = color;
emitPosition = emitPos;
emitDirection = emitDir;
emitSpeed = speed;
emitNumber = num;
}
// 准备下一次发射
public void prepareToEmitDisk() {
if (counting == false && shooting == false) {
timeToEmit = countDown;
emitEnable = true; // 可发射变为真
}
}
// 发射飞碟
void emitDisks() {
for (int i = 0; i < emitNumber; ++i) {
diskIds.Add(Factory.getInstance().getDisk());
disks.Add(Factory.getInstance().getDiskObject(diskIds[i]));
disks[i].transform.localScale *= diskScale;
disks[i].transform.position = new Vector3(emitPosition.x, emitPosition.y + i, emitPosition.z);
disks[i].SetActive(true);
disks[i].rigidbody.AddForce(emitDirection * Random.Range(emitSpeed * 5, emitSpeed * 10) / 10, ForceMode.Impulse);
}
}
// 回收
void freeADisk(int i) {
Factory.getInstance().free(diskIds[i]);
disks.RemoveAt(i);
diskIds.RemoveAt(i);
}
void FixedUpdate() {
if (timeToEmit > 0) {
counting = true;
timeToEmit -= Time.deltaTime;
} else {
counting = false;
if (emitEnable == true) {
emitDisks();
emitEnable = false; // 改变之后可发射变为假
shooting = true;
}
}
}
void Update() {
for (int i = 0; i < disks.Count; i++) {
if (!disks[i].activeInHierarchy) {
scene.getJudge().scoreADisk();
freeADisk(i);
} else if (disks[i].transform.position.y < 0) {
scene.getJudge().failADisk();
freeADisk(i);
}
}
if (disks.Count == 0) { // 如果不存在飞碟了,停止射击
shooting = false;
}
}
}
这个文件控制的是游戏场景,通过调用Factory.getInstance()功能来获取飞碟的实例,当飞碟被击中或者自己落地的时候,将被freeDisk()函数回收,并且通过调用Judge类中的函数,来决定分数的获得和扣除,并以此来决定是否结束游戏或者进入下一关卡。FixedUpdate()和Update()函数通过bool条件判断,来决定是否可以继续射击。
###2、UserInterface###
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using Com.Mygame;
public class UserInterface : MonoBehaviour {
public Text mainText;
public Text scoreText;
public Text roundText;
private int round; // 判定当前回合
public GameObject bullet;
public ParticleSystem explosion;
public float fireRate = .25f;
public float speed = 500f;
private float nextFireTime;
private IUserInterface userInt;
private IQueryStatus queryInt;
void Start() { // 游戏开始,加载
bullet = GameObject.Instantiate(bullet) as GameObject;
explosion = GameObject.Instantiate(explosion) as ParticleSystem;
userInt = SceneController.getInstance() as IUserInterface;
queryInt = SceneController.getInstance() as IQueryStatus;
}
void Update() {
if (queryInt.isCounting()) {
mainText.text = ((int)queryInt.getEmitTime()).ToString();
} else {
if (Input.GetKeyDown("space")) { // 输入空格开始
yield return new WaitforSeconds(3f); // 倒数3秒后开始
userInt.emitDisk();
}
if (queryInt.isShooting()) {
mainText.text = ""; // 隐藏maintext
}
// 发射子弹
if (queryInt.isShooting() && Input.GetMouseButtonDown(0) && Time.time > nextFireTime) {
nextFireTime = Time.time + fireRate; // 开火冷却时间
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
bullet.rigidbody.velocity = Vector3.zero; // 重置子弹速度
bullet.transform.position = transform.position; // 子弹射出
bullet.rigidbody.AddForce(ray.direction * speed, ForceMode.Impulse);
RaycastHit hit;
if (Physics.Raycast(ray, out hit) && hit.collider.gameObject.tag == "Disk") {
explosion.transform.position = hit.collider.gameObject.transform.position;
explosion.Play();
// 击中飞碟自动回收
hit.collider.gameObject.SetActive(false);
}
}
}
roundText.text = "Round: " + queryInt.getRound().ToString();
scoreText.text = "Score: " + queryInt.getPoint().ToString();
if (round != queryInt.getRound()) {
round = queryInt.getRound();
mainText.text = "Round " + round.ToString() + " Start";
}
}
}
该文件创建用户界面,其中包含着加载、提示、游戏主体等部分。作业要求中,用户按空格后,321倒数3秒,飞碟飞出(物理引擎控制),点击鼠标左键,子弹飞出。飞碟落地,或被击中,则准备下一次射击。我用了waitforSeconds函数来实现,在等待3秒之后,开始飞出飞碟,飞碟落地或被击中的函数已经在GameModel.cs文件中写出,这里就不再赘述。值得一提的是,刚开始我测试游戏的时候,子弹的速度会越来越快,这是因为我没有将其清零的缘故,后来我令其velocity赋值为0来进行清零。上一次的作业中我的子弹使用的是射线判定,这次则用的是有碰撞体积的物理引擎,这点可以在装载之后发现。
###3、SceneController.cs###
using UnityEngine;
using System.Collections;
using Com.Mygame;
namespace Com.Mygame {
public interface IUserInterface { // 场景控制器,是游戏中十分重要的一个环节
void emitDisk();
}
public interface IQueryStatus { // 记录回合和得分
bool isCounting();
bool isShooting();
int getRound();
int getPoint();
int getEmitTime();
}
public interface IJudgeEvent {
void nextRound();
void setPoint(int point);
}
public class SceneController : System.Object, IQueryStatus, IUserInterface, IJudgeEvent { // 继承各类
private static SceneController _instance;
private SceneControllerBC _baseCode; // 分别为SceneControllerBC、GameModel、Judege
private GameModel _gameModel;
private Judge _judge;
private int _round;
private int _point;
public static SceneController getInstance() {
if (_instance == null) {
_instance = new SceneController(); // 返回SceneController的实例
}
return _instance;
}
public void setGameModel(GameModel obj) {
_gameModel = obj;
}
internal GameModel getGameModel() {
return _gameModel;
}
public void setJudge(Judge obj) {
_judge = obj;
}
internal Judge getJudge() {
return _judge;
}
public void setSceneControllerBC(SceneControllerBC obj) {
_baseCode = obj;
}
internal SceneControllerBC getSceneControllerBC() {
return _baseCode;
}
public void emitDisk() {
_gameModel.prepareToEmitDisk();
}
public bool isCounting() {
return _gameModel.isCounting();
}
public bool isShooting() {
return _gameModel.isShooting();
}
public int getRound() {
return _round;
}
public int getPoint() {
return _point;
}
public int getEmitTime() {
int result = (int)_gameModel.timeToEmit + 1;
return result;
}
public void setPoint(int point) {
_point = point;
}
public void nextRound() {
_point = 0; _baseCode.loadRoundData(++_round);
}
}
}
场景控制器,实现各种成员变量的返回实现,以及接口定义和保存注入对象。其中它有两个私有变量round和point,分别记录游戏正在进行的回合,以及玩家目前的得分,应用在GameModel中实现。
###4、SceneControllerBC.cs###
UnityEngine;
using System.Collections;
using Com.Mygame;
public class SceneControllerBC : MonoBehaviour {
private Color color;
private Vector3 emitPos;
private Vector3 emitDir;
private float speed;
void Awake() {
SceneController.getInstance().setSceneControllerBC(this);
}
public void loadRoundData(int round) { // 关卡的设计
switch (round) {
case 1: // 第一关
color = Color.green;
emitPos = new Vector3(-2.5f, 0.2f, -5f); // 初始条件
emitDir = new Vector3(24.5f, 40.0f, 67f);
speed = 4;
SceneController.getInstance().getGameModel().setting(1, color, emitPos, emitDir.normalized, speed, 1);
break;
case 2: // 第二关
color = Color.red;
emitPos = new Vector3(2.5f, 0.2f, -5f);
emitDir = new Vector3(-24.5f, 35.0f, 67f);
speed = 4;
SceneController.getInstance().getGameModel().setting(1, color, emitPos, emitDir.normalized, speed, 2); // 设定条件
break;
case 3: // 第三关
color = Color.red;
emitPos = new Vector3(2.5f, 0.2f, -5f);
emitDir = new Vector3(-24.5f, 35.0f, 67f); // 飞碟初始位置不变,仅改变速度
speed = 5;
SceneController.getInstance().getGameModel().setting(1, color, emitPos, emitDir.normalized, speed, 4); // 其实改一下飞碟的速度就可以了
break;
}
}
}
此文件为关卡类的定义,我只做了3个关卡,题目要求我:游戏要分多个 round , 飞碟数量每个 round 都是 n 个,但色彩,大小;发射位置,速度,角度,每次发射数量按预定规则变化。因此我没有改变飞碟的数量,位置和角度,从速度入手,越到后面的关卡越快。函数Awake()用来获取场景控制器实例,loadRoundData()用来初始化游戏场景,即定义飞碟的属性。
###5、Factory.cs###
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Com.Mygame;
namespace Com.Mygame {
public class Factory : System.Object {
private static Factory _instance; // 获取实例
private static List<GameObject> diskList;
public GameObject diskTemplate;
public static Factory getInstance() { // 工厂实例
if (_instance == null) {
_instance = new Factory();
diskList = new List<GameObject>();
}
return _instance;
}
public int getDisk() {
for (int i = 0; i < diskList.Count; i++) {
if (!diskList[i].activeInHierarchy) { // 判断是否飞碟空闲
return i;
}
}
diskList.Add(GameObject.Instantiate(diskTemplate) as GameObject); // 设置新的飞碟
return diskList.Count-1;
}
public void free(int id) {
if (id >= 0 && id < diskList.Count) { // 判断是否有效
diskList[id].rigidbody.velocity = Vector3.zero; // 速度清零
diskList[id].transform.localScale = diskTemplate.transform.localScale;
diskList[id].SetActive(false); // 活动能力重置
}
}
public GameObject getDiskObject(int id) {
if (id > -1 && id < diskList.Count) {
return diskList[id];
}
return null;
}
}
}
public class DiskFactoryBC : MonoBehaviour { // 另一个类BC
public GameObject disk;
void Awake() {
Factory.getInstance().diskTemplate = disk; // 用于获取飞碟实例
}
}
题目要求:飞碟用一个带缓存的工厂生产,template 中放置预制的飞碟对象。这个就是飞碟工厂,管理飞碟实例,同时对外屏蔽飞碟实例的的提取和回收细节。它定义了获取、回收飞碟的功能,并且由于是public函数,可以被其他函数直接调用,来管理、应用飞碟。
###6、Judge.cs###
using UnityEngine;
using System.Collections;
using Com.Mygame;
public class Judge : MonoBehaviour { // 判定得分失分,能否进入下一回合
public int oneDiskScore = 10;
public int oneDiskFail = 10;
public int disksToWin = 4;
private SceneController scene;
void Awake() {
scene = SceneController.getInstance();
scene.setJudge(this); // 设定规则
}
void Start() {
scene.nextRound(); // 第一关
}
public void scoreADisk() // 得分
{
scene.setPoint(scene.getPoint() + oneDiskScore);
if (scene.getPoint() == disksToWin * oneDiskScore) {
scene.nextRound();
}
}
public void failADisk() { // 失分
scene.setPoint(scene.getPoint() - oneDiskFail); // 判定条件,飞碟掉落
}
}
用以判断得失分的类,当符合得分条件时,调用得分函数;当符合失分条件时(即飞碟未击中而掉落时),调用失分函数。当得分符合条件时,进入下一回合。
*题目条件:有一支枪在摄像机位置(0,1,-10),在(0,0,0-10-20)放置三个小球作为距离标记,调整视角直到小球在下中部。*
部件设定:
摄像机:
飞碟:
子弹:
标记球:
1、
2、
3、
最后在摄像机上挂载文件就可以了。一个射飞碟的小游戏就做好了。