unity3d之打飞碟

本文介绍了使用Unity3D开发打飞碟游戏的过程,通过代码复用和设计模式,如SSDirector、ISceneController和Moveable,简化开发工作。文章提到了FirstController的关键实现,包括资源加载和碰撞检测,以及遇到的问题和解决方案。UserGUI部分参考了优秀博客并实现了自己的逻辑。UFOFactory负责创建和回收UFO,维护两个链表以管理游戏对象的生命周期。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

演示视频及完整代码请前往:
github地址
首先贴出本项目的UML图,如下:
在这里插入图片描述
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KlcBnx21-1570634015170)(typora_pic\ufo.svg)]

在做这次作业之前,仔细想想可以发现之前做的牧师与魔鬼中的代码有很多可以复用。比如说SSDirector,ISceneController,IUserAction,Moveable。这就体现出规范代码的好处了,做这次作业的时候只要将上面的类稍微修改一些即可。接下来我们来看其他的类。

首先看到FirstController,其比较重要的两个成员变量时userGUI和ufo_factory。FirstController的工作量比较大,包括加载资源,判定是否击中等。代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using mygame;

public class FirstController : MonoBehaviour, SceneController, UserAction
{
    public UFOFactor disk_factory;
    public UserGUI user_gui;
	
    private int round = 1;                                                   //回合
    private float speed = 2f;                                                //发射一个飞碟的时间间隔
    private int curScore = 0;
	private int curLife = 6;
	private bool playing_game = false;                                       //游戏中
    private bool game_over = false;                                          //游戏结束
    private bool game_start = false;                                         //游戏开始
	private int score_round2 = 10;                                           //去到第二回合所需分数
    private int score_round3 = 25;                                           //去到第三回合所需分数
	private List <UFO> this_trival_ufos = new List<UFO>();
	private List <UFO> disk_notshot = new List<UFO>();
	
    void Start ()
    {
		Debug.Log("right here FirstController 1");
        Director director = Director.getInstance();     
        director.currentSceneController = this;             
        disk_factory = Singleton<UFOFactor>.Instance;
        user_gui = gameObject.AddComponent<UserGUI>() as UserGUI;
    }
	
	void Update ()
    {
        if(game_start)
        {
            //游戏结束,取消定时发送飞碟
            if (game_over)
            {
                CancelInvoke("LoadResources");
            }
            //设定一个定时器,发送飞碟,游戏开始
            if (!playing_game)
            {
				Debug.Log("right here FirstController 2");
                InvokeRepeating("LoadResources", 1f, speed);
                playing_game = true;
            }
            //发送飞碟
            FlyUFO();
            //回合升级
            if (curScore >= score_round2 && round == 1)
            {
				Debug.Log("level up");
                round = 2;
                //缩小飞碟发送间隔
                speed = speed - 0.6f;
                CancelInvoke("LoadResources");
                playing_game = false;
            }
            else if (curScore >= score_round3 && round == 2)
            {
                round = 3;
                speed = speed - 0.3f;
                CancelInvoke("LoadResources");
                playing_game = false;
            }
        }
    }

	public void FlyUFO() {
		if (game_over) return;
		// Debug.Log("right here FirstController 2");
		// Debug.Log(this_trival_ufos.Count);
		for (int i = 0;i < this_trival_ufos.Count;i ++){
			
			this_trival_ufos[i].ufo.SetActive(true);
			disk_notshot.Add(this_trival_ufos[i]);
			
			this_trival_ufos[i].Fly();
			
			this_trival_ufos.Remove(this_trival_ufos[i]);
			i --;
		}
		Debug.Log("count");
		Debug.Log(disk_notshot.Count);
		for (int i = 0; i < disk_notshot.Count; i++)
        {
            GameObject temp = disk_notshot[i].ufo;
            if (temp.transform.position.x > 18 && temp.gameObject.activeSelf == true)
            {
                disk_factory.FreeDisk(disk_notshot[i]);
                disk_notshot.Remove(disk_notshot[i]);
                //玩家血量-1
                user_gui.ReduceBlood();
            }
        }
	}
    public void LoadResources()
    {
		Debug.Log("right here FirstController 3");
		disk_factory = Singleton<UFOFactor>.Instance;
        this_trival_ufos = disk_factory.GetDisk(round); 
    }


    public void Hit(Vector3 pos)
    {
		Debug.Log(pos);
		int index = -1;
		for(int i = 0;i < disk_notshot.Count;i ++){
			if(hited(pos,disk_notshot[i].ufo.transform.position)){
				Debug.Log(disk_notshot[i].ufo.transform.position);
				index = i;
				break;
			}
		}
		if(index == -1) return;
		
		curScore += disk_notshot[index].score;
		disk_factory.FreeDisk(disk_notshot[index]);
        disk_notshot.Remove(disk_notshot[index]);

        
    }
	
	public bool hited(Vector3 posScreen, Vector3 posObject){
		float xx = posScreen.x-(posObject.x * 22) - 512;
		float yy = posScreen.y-(posObject.y * 22) - 385;
		
		
		if(xx*xx + yy* yy < 1600 && yy*yy<200){
			Debug.Log(xx);
			Debug.Log(yy);
			return true;
		}
			
		return false;
	}
    public int GetScore()
    {
        return curScore;
    }
    public void ReStart()
    {
        game_over = false;
        playing_game = false;
        curScore = 0;
        round = 1;
        speed = 2f;
    }
    public void GameOver()
    {
        game_over = true;
		CancelInvoke("LoadResources");
    }

    public void BeginGame()
    {
        game_start = true;
    }
}

上面这段代码中,我有一个地方做的不是很好。判断是否击中时,首选应该是使用Ray,但是不知道为什么,我无法选中点击的gameObject,因此只好根据点击的位置和飞碟的位置来判断是否击中。

至于UserGUI,我参考了老师给出的优秀博客,但是内部逻辑我是按照自己的想法来的。

最后说一说UFOFactor:

UFOFactor主要做两件事,一个是提供UFO,一个是回收UFO以供下次使用。这个类中维护了两个链表,空闲链表维护的是之前用过的UFO,使用中的链表维护的是将要提供的UFO,代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using mygame;

public class UFOFactor : MonoBehaviour
{
    private List<UFO> used = new List<UFO>();   //正在被使用的飞碟列表
    private List<UFO> free = new List<UFO>();   //空闲的飞碟列表

    public List <UFO> GetDisk(int round)
    {
		Debug.Log("right here UFOFactor 1");
        int choice = 0;
        int scope1 = 1, scope2 = 2, scope3 = 3;           //随机的范围
        float start_y = -10f;                             //刚实例化时的飞碟的竖直位置
		int ufo_num = Random.Range(1, round + 1);
		int counts = 0;
		// 清空used
		used = new List<UFO>();
        // 根据回合,选择要飞出的UFO的种类
		
		for(int i=0;i<free.Count;i++) {
			Debug.Log("not empty");
			int type = Random.Range(1, round+1);
			if(free[i].type == type) {
				used.Add(free[i]);
				free.Remove(free[i]);
				i --;
				counts ++;
				if(counts == ufo_num) 
					break;
			}
		}
		
		if(counts < ufo_num){
			for (int i = 0;i < ufo_num-counts;i ++){
				int type = Random.Range(1, round);
				UFO new_ufo = new UFO(type);
				used.Add(new_ufo);
			}
		}
		return used;
    }

    // 回收飞碟
    public void FreeDisk(UFO aUFO)
    {
		aUFO.ufo.SetActive(false);
		aUFO.ufo.transform.position = Vector3.zero;
		free.Add(aUFO);
    }
}

内容概要:文章基于4A架构(业务架构、应用架构、数据架构、技术架构),对SAP的成本中心和利润中心进行了详细对比分析。业务架构上,成本中心是成本控制的责任单元,负责成本归集与控制,而利润中心是利润创造的独立实体,负责收入、成本和利润的核算。应用架构方面,两者都依托于SAP的CO模块,但功能有所区分,如成本中心侧重于成本要素归集和预算管理,利润中心则关注内部交易核算和获利能力分析。数据架构中,成本中心与利润中心存在多对一的关系,交易数据通过成本归集、分摊和利润计算流程联动。技术架构依赖SAP S/4HANA的内存计算和ABAP技术,支持实时核算与跨系统集成。总结来看,成本中心和利润中心在4A架构下相互关联,共同为企业提供精细化管理和决策支持。 适合人群:从事企业财务管理、成本控制或利润核算的专业人员,以及对SAP系统有一定了解的企业信息化管理人员。 使用场景及目标:①帮助企业理解成本中心和利润中心在4A架构下的运作机制;②指导企业在实施SAP系统时合理配置成本中心和利润中心,优化业务流程;③提升企业对成本和利润的精细化管理水平,支持业务决策。 其他说明:文章不仅阐述了理论概念,还提供了具体的应用场景和技术实现方式,有助于读者全面理解并应用于实际工作中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值