3D游戏编程与设计作业05

单例设计模式

单例(Singleton)模式的定义:指一个类只有一个实例,且该类能自行创建这个实例的一种模式。
单例模式有3个特点:

  1. 单例类只有一个实例对象;
  2. 该单例对象必须由单例类自行创建;
  3. 单例类对外提供一个访问该单例的全局访问点
  • 单例类的构造函数为私有,外部类无法调用构造函数,无法生成多个实例
  • 单例类必须自身定义一个静态私有实例,并向外提供一个静态的公有函数用于创建或获取该静态实例

单例模式通常有两种实现形式:

  • 懒汉式单例
    类加载时没有生成单例,只有当第一次调用getInstance方法时才去创建这个单例
  • 饿汉式单例
    类一旦加载就创建一个单例,保证在调用getInstance方法之前单例已经存在了

鼠标打飞碟(Hit UFO)游戏

要求

游戏内容要求

  • 游戏有 n 个 round,每个 round 都包括10 次 trial;
  • 每个 trial 的飞碟的色彩、大小、发射位置、速度、角度、同时出现的个数都可能不同。它们由该 round 的 ruler 控制;
  • 每个 trial 的飞碟有随机性,总体难度随 round 上升;
  • 鼠标点中得分,得分规则按色彩、大小、速度不同计算,规则可自由设定。

程序设计要求

  • 使用带缓存的工厂模式管理不同飞碟的生产与回收,该工厂必须是场景单实例的!具体实现见参考资源 Singleton 模板类
  • 近可能使用前面 MVC 结构实现人机交互与游戏模型分离

程序设计

MVC架构

首先搭建MVC架构,其中的MVC架构模型可以直接借用(copy)上一次牧师与魔鬼游戏的架构设计代码。

  • 模型

    • 架构模型
      • ISceneController(interface)
      • SSAction(继承ScriptableObject)
      • SSActionEventType(enum类型)
      • ISSActionCallback(interface)
      • SequenceAction(继承SSActionISSActionCallback
      • SSDirector(继承System.Object
      • SSActionManager(继承MonoBehaviouISSActionCallback)
      • Singleton<T>
    • 游戏对象模型
      • UFOData(继承MonoBehaviour)
      • UFOFactory(继承MonoBehaviour)
      • Judge(继承MonoBehaviour)
      • JoyStick(继承MonoBehaviour)
      • SpaceCraft
    • 动作事件模型
      • FlyAction(继承SSAction)
      • FlyActionManger(继承SSActionManager)
      • IUserAction用户动作列表(interface)
    动作参数结果
    启动游戏游戏初始界面
    重新开始游戏初始界面
    用户点击游戏界面点击位置pos击中飞碟与否
  • 控制器

    • Controller(继承MonoBehaviourISceneControllerIUserAction)
  • 界面

    • UserGUI

场景单实例的工厂

应本次程序设计的要求,还需要使用带缓存的工厂模式管理不同飞碟的生产与回收,该工厂必须是场景单实例的。

工厂模式
意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
关键代码:创建过程在其子类执行。

在本例中运用模板,可以为每个MonoBehaviour子类创建一个对象的实例。Singleton代码如图所示:

//Singleton.cs
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;  
		}  
	}
}

要使用场景单例,只需要将MonoBehavior子类对象挂载到任何一个游戏对象上即可,然后在任意位置可以通过Singleton<YourMnoType>.Instance获得该对象。

游戏规则说明

  1. 每一轮游戏,生命值为6;每未击中一个飞碟则扣除1点生命值;当生命值降为0时,游戏结束
  2. 鼠标点击飞碟可击中飞碟,每击中一个飞碟可获得5分
  3. 达到10分可进入第二回合;达到25分可进入第三回合
  4. 第一个回合飞碟颜色为绿色;第二个回合飞碟颜色为蓝色;第三个回合飞碟颜色为红色
  5. wasd键控制飞机上左下右移动,保证飞机不要与飞碟发生碰撞,否则生命值将直接降为0,游戏结束
  6. 随着回合数的增加,飞碟出现和移动速度将加快

详细代码

代码传送门

游戏演示视频

前往B站观看游戏demo演示视频

编写一个简单的自定义Component

要求:用自定义组件定义几种飞碟,做成预制

例如,本次游戏设计中的 UFOInspector.cs(文件目录:Assets/Editor)

所有编辑器类的代码,都需要放在Editor文件夹下,只有这样Unity才能正确的识别这代码。Editor的名字对就行,放在哪倒无所谓。

using UnityEditor;
using UnityEngine;
using System.Collections;

// Custom Editor using SerializedProperties.
// Automatic handling of multi-object editing, undo, and Prefab overrides.
[CustomEditor(typeof(UFOData))]
[CanEditMultipleObjects]
public class MyPlayerEditor : Editor
{
    SerializedProperty score;
    SerializedProperty color;
    //SerializedProperty direction;
    SerializedProperty scale;

    void OnEnable()
    {
        // Setup the SerializedProperties.
        score = serializedObject.FindProperty("score");
        color = serializedObject.FindProperty("color");
        //direction = serializedObject.FindProperty("direction");
        scale = serializedObject.FindProperty("scale");
    }

    public override void OnInspectorGUI()
    {
        // Update the serializedProperty - always do this in the beginning of OnInspectorGUI.
        serializedObject.Update();

        // Show the custom GUI controls.
        EditorGUILayout.PropertyField(score, new GUIContent("score"));
        EditorGUILayout.PropertyField(color, new GUIContent("color"));
        //EditorGUILayout.PropertyField(scale, new GUIContent("direction"));
        EditorGUILayout.PropertyField(scale, new GUIContent("scale"));

        // Apply changes to the serializedProperty - always do this in the end of OnInspectorGUI.
        serializedObject.ApplyModifiedProperties();
    }

    // Custom GUILayout progress bar.
    void ProgressBar(float value, string label)
    {
        // Get a rect for the progress bar using the same margins as a textfield:
        Rect rect = GUILayoutUtility.GetRect(18, 18, "TextField");
        EditorGUI.ProgressBar(rect, value, label);
        EditorGUILayout.Space();
    }
}

参考文献

潘老师的课程网站
singleton详解
工厂模式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值