Unity打飞碟游戏

  • 游戏内容要求:
    1. 游戏有 n 个 round,每个 round 都包括10 次 trial;
    2. 每个 trial 的飞碟的色彩、大小、发射位置、速度、角度、同时出现的个数都可能不同。它们由该 round 的 ruler 控制;
    3. 每个 trial 的飞碟有随机性,总体难度随 round 上升;
    4. 鼠标点中得分,得分规则按色彩、大小、速度不同计算,规则可自由设定。
  • 游戏的要求:
    • 使用带缓存的工厂模式管理不同飞碟的生产与回收,该工厂必须是场景单实例的!具体实现见参考资源 Singleton 模板类
    • 近可能使用前面 MVC 结构实现人机交互与游戏模型分离
    • 必须使用对象池管理飞碟对象。
    • 建议使用物理引擎管理飞碟飞行路径。

对象池:

        对象池(Object Pool)是一种用于高效管理和复用对象的设计模式,特别是在需要频繁创建和销毁大量相似对象的场景中(如子弹、敌人、特效等)。其核心思想是:当你不再需要一个对象时,并不是销毁它,而是将它返回池中,以便以后重用,避免了反复的内存分配和垃圾回收的开销,从而提高性能。

伪代码如下:

class ObjectPool:
    // 对象池的构造函数,初始化池,设定池的大小和对象类型
    function initialize(prefab, initialSize):
        pool = empty list
        this.prefab = prefab  // 对象的预设(或模板)
        
        // 填充池
        for i from 1 to initialSize:
            obj = createNewObject(prefab)  // 创建一个新的对象
            obj.setActive(false)  // 初始对象不活动(不显示)
            pool.add(obj)
        
    // 从池中获取一个对象
    function getObject():
        // 查找一个未激活的对象
        for obj in pool:
            if obj.isActive() == false:
                obj.setActive(true)  // 激活对象
                return obj
        
        // 如果池中没有可用对象,则创建新对象
        newObj = createNewObject(prefab)
        pool.add(newObj)
        return newObj
    
    // 将一个对象归还到池中
    function returnObject(obj):
        obj.setActive(false)  // 禁用对象
        // 此时对象会被池重新管理,等待下次使用
        
    // 创建一个新的对象
    function createNewObject(prefab):
        // 根据预设(或模板)创建新对象
        return new Object(prefab)

游戏代码实现:

(一)动作类和动作管理器

        在上一个游戏框架,运动动力学基础上增加物理刚体运动:

        物体添加刚体属性后,本身就有了重力,只需要一个水平方向的初速度。

        用物理刚体实现的飞碟动作类和飞碟动作管理类如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
//飞碟动作类(物理刚体运动)
public class PhysicFlyAction : SSAction
{
    public float speedX;
    public static PhysicFlyAction GetSSAction(float x) {
        PhysicFlyAction action = ScriptableObject.CreateInstance<PhysicFlyAction>();
        action.speedX = x;
        return action;
    }
    // Start is called before the first frame update
    public override void Start()
    {

        gameObject.GetComponent<Rigidbody>().isKinematic = false;
   
        gameObject.GetComponent<Rigidbody>().velocity = new Vector3(speedX * 10, 0, 0);
 
        gameObject.GetComponent<Rigidbody>().drag = 1;
    }
 
    // Update is called once per frame
    public override void Update()
    {
   
        if (this.transform.gameObject.activeSelf == false) {

            this.destroy = true;
 
            this.callback.SSActionEvent(this);

            return;
        }

        Vector3 vec3 = Camera.main.WorldToScreenPoint (this.transform.position);

        if (vec3.x < -100 || vec3.x > Camera.main.pixelWidth + 100 || vec3.y < -100 || vec3.y > Camera.main.pixelHeight + 100) {

            this.destroy = true;
  
            this.callback.SSActionEvent(this);

            return;
        }
    }
}
 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
//(物理刚体)动作管理器
//Adapter模式
public class PhysicActionManager : SSActionManager, IActionCallback, IActionManager
{

    public RoundController sceneController;

    public PhysicFlyAction action;

    public DiskFactory factory;
    
    // Start is called before the first frame update
    protected new void Start()
    {

        sceneController = (RoundController)SSDirector.getInstance().currentSceneController;

        sceneController.actionManager = this as IActionManager;

        factory = Singleton<DiskFactory>.Instance;
    }
 
    //Update is called once per frame
    protected new void Update(){}
 
    public void SSActionEvent(SSAction source,
        SSActionEventType events = SSActionEventType.Completed,
        int intParam = 0,
        string strParam = null,
        Object objectParam = null) {

            factory.FreeDisk(source.transform.gameObject);
    }
 
    public override void MoveDisk(GameObject disk) {

        action = PhysicFlyAction.GetSSAction(disk.GetComponent<DiskAttributes>().speedX);

        RunAction(disk, action, this);
    }
 
    public void Fly(GameObject disk) {
        MoveDisk(disk);
    }

    public int RemainActionCount() {
        return actions.Count;
    }
}

(二)控制器类

(三)用户接口和UI

Github地址:fang2368/mycode

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值