游戏简介
游戏中随机出现飞碟,玩家在其坠地之前点击到即可得分,每个飞碟的分数由其速度、大小决定,在50秒内取得50分即可进入下一轮,否则结束游戏、结算分数。随着轮数的增加,飞碟的平均速度逐渐增加,平均大小逐渐减小,从而提高难度。
游戏演示视频
【3d游戏编程作业5——打飞碟小游戏】 https://www.bilibili.com/video/BV1ew411T7CF/?share_source=cop...
游戏代码
https://github.com/Kmbls/hit-UFO
新增技术
1、使用了对象池技术,UFOFactory类负责飞碟的生成与回收。通过复用已生成的对象,可以节约内存。
对象池伪代码如下:
getUFO(UFOData)
BEGIN
IF (free list has UFO) THEN
a_UFO = remove one from list
ELSE
a_UFO = clone from Prefabs
ENDIF
Set UFOData of a_UFO
Add a_UFO to used list
Return a_UFO
END
FreeDisk(ufo)
BEGIN
Find ufo in used list
IF (not found) THEN THROW exception
Move ufo from used to free list
END
2、使用物理引擎控制飞碟移动。通过给飞碟预制件添加刚体组件,并在发射飞碟时给予其速度矢量,可模拟飞碟被发射后的真实运动轨迹。
3、场景单实例。使用Singleton<T>.Instance,可在任何地方获取继承自MonoBehavior的单实例对象。
游戏框架
FirstController与ISceneController、SSDirector等类的关系依旧不变,在此不再画出,详见之前作业报告。
重要代码
1、Singleton<T>
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
protected static T instance;
public static T Instance {
get {
if (instance == null) {
instance = (T)FindObjectOfType (typeof(T));
if (instance == null) {
Debug.LogError ("An instance of " + typeof(T) +
" is needed in the scene, but there is none.");
}
}
return instance;
}
}
}
2、UFOFactory
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices.WindowsRuntime;
using UnityEngine;
struct Rule {
}
public class UFOFactory : MonoBehaviour
{
private List<GameObject> uselist;
private List<GameObject> freelist;
// Start is called before the first frame update
void Start()
{
Debug.Log("UFOFactory Start!");
uselist = new List<GameObject>();
freelist = new List<GameObject>();
}
// Update is called once per frame
void Update()
{
}
public GameObject GetUFO(UFOData data){
GameObject ufo = null;
bool found = false;
if(freelist.Count != 0){
foreach (GameObject o in freelist){
if(o.tag == data.color){
ufo = o;
freelist.Remove(ufo);
found = true;
break;
}
}
}
if(found == false){
ufo = Instantiate<GameObject>(
Resources.Load<GameObject>("prefabs/" + data.color),
Vector3.up,Quaternion.Euler(0,0,180f));
}
ufo.tag = data.color;
ufo.name = data.score.ToString();
ufo.GetComponent<Rigidbody>().mass = data.mass;
ufo.transform.localScale = new Vector3(data.size,data.size,data.size);
uselist.Add(ufo);
return ufo;
}
public void FreeUFO(GameObject ufo){
foreach(GameObject o in uselist){
if(o.GetInstanceID() == ufo.GetInstanceID()){
o.SetActive(false);
uselist.Remove(o);
freelist.Add(o);
break;
}
}
}
}
使用两个List维护对象池,在原需要释放对象时,改为存入空闲列表。需要调用对象时,先在空闲列表中寻找有无满足条件的对象,有则拿出使用,从而减少了对象的重复生成与销毁,减少内存占用。
3、UFOData
public struct UFOData
{
public int size;
public string color;
public float mass;
public int score;
}
4、RoundController
public class RoundController : MonoBehaviour
{
public int round;
private float shootdelay;
public float time;
public float total_time;
public bool ongame;
// Start is called before the first frame update
void Start()
{
Debug.Log("RoundController Start!");
round = 1;
shootdelay = 2;
ongame = true;
time = 0;
total_time = 0;
}
// Update is called once per frame
void Update()
{
if(ongame){
time += Time.deltaTime;
total_time += Time.deltaTime;
if(time > 1)
Singleton<UserGUI>.Instance.UpdateTime();
if(time > shootdelay){
int times = Random.Range(1, 5);
for (int i = 0;i<times;i++)
createUFO();
time = 0;
}
if(total_time > 50){
Singleton<FirstController>.Instance.GameOver();
}
}
}
public void createUFO(){
UFOData data = new UFOData();
data.size = Random.Range(2,5);
int color = Random.Range(0,3);
switch(color){
case 0:
data.color = "Red";break;
case 1:
data.color = "Blue";break;
case 2:
data.color = "White";break;
}
data.mass = Random.Range(1,2);
float speedfactor = (float)Random.Range(1 + (float)(0.5*round < 3.5 ? 0.5*round : 3.5),5);
data.score = (int)(speedfactor * 5 / data.size);
GameObject ufo = Singleton<UFOFactory>.Instance.GetUFO(data);
Singleton<UFOActionManager>.Instance.setMove(ufo,speedfactor);
}
}
按照一定规则生成UFOdata,并交由UFOFactory生成对象。取得对象后,再将对象交由UFOActionManager赋予动作。
同时维护游戏时间,超时则游戏结束。
5、ScoreController
public class ScoreController : MonoBehaviour
{
public int total_score;
public int now_score;
public int score_to_next;
// Start is called before the first frame update
void Start()
{
Debug.Log("ScoreController Start!");
now_score = 0;
score_to_next = 50;
}
// Update is called once per frame
void Update()
{
}
public void AddScore(GameObject ufo){
int add_score;
int.TryParse(ufo.name,out add_score);
now_score += add_score;
total_score += add_score;
if(now_score >= score_to_next){
Singleton<FirstController>.Instance.Brake();
}
Singleton<UserGUI>.Instance.UpdateScore();
}
}
添加、记录得分,并在满足得分要求后进入下一轮。
6、FlyAction
public class FlyAction : SSAction
{
private Vector3 velocity;
private Vector3 spawnpos;
private Rigidbody rb;
// Start is called before the first frame update
public static FlyAction GetFlyAction(Vector3 velocity, Vector3 spawnpos){
FlyAction action = ScriptableObject.CreateInstance<FlyAction> ();
action.velocity = velocity;
action.spawnpos = spawnpos;
return action;
}
public override void Start()
{
gameobject.transform.position = spawnpos;
gameobject.SetActive(true);
rb = gameobject.GetComponent<Rigidbody>();
//rb.MovePosition(spawnpos);
rb.velocity = velocity;
}
public override void Update()
{
if(gameobject.transform.position.y <= 0){
Debug.Log(gameobject.transform.position.y);
Singleton<UFOFactory>.Instance.FreeUFO(gameobject);
this.destory = true;
}
}
}
赋予刚体组件以初速度和初位置,从而交由物理引擎管理物体动作。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。