帮你理清静态类和单例

本文聚焦于Unity游戏开发中静态类与单例的使用。介绍了单例常用于管理类,可继承MonoBehaviour,自带生命周期且支持可视化参数编辑,还能随场景切换销毁;而静态类不能继承,成员一直存在直到应用退出,适用于游戏存档管理。

大家都知道什么是静态类,什么是单例,但是在使用unity做游戏的过程中其实我对这两个名词还是感觉没有清晰的区分,到底应该在什么时候该用静态类,什么时候该用单例呢?他们使用之后的差别又到底在哪里呢?今天我就通过一些实际在项目中的代码来理一理他们俩吧。

  • 单例常用情景:大部分管理类的使用
大家在游戏中最常用的一种类就是管理类了,什么GameManager,SoundManager,这些一般都是单例类,我们的目的也就是想要在游戏中只存在一个这样的类,然后通过这个唯一实例化的管理类来进行一些管理行为。那么,静态类不是也是唯一的吗?为啥不用静态类来做呢?我这里就用一个最常用的子弹对象池的管理类来做一个对比分析吧。
我先来写一个非常简易的子弹对象池的单例类: 那么,如果用静态类能不能做到这个事情呢?能不能也用来管理一个对象池呢?答案是当然可以,接下来我就用静态类写一个,然后分析一下为什么用单例,而不用静态类。 可以看出静态类也是可以完全实现我们的需求功能的,但是,接下来我们一步一步的分析一下为什么静态类不适合作为对象池的管理类。
  1. 静态类不能继承。 图2和图1的第一个不同点,就是静态类并没有继承MonoBehaviour,这是因为静态类本身是不能继承其他类的,那么,他也就失去了很多单例类的优势,单利本身是可以实例化的,只是单例模式确保了实例化的这个类对象的唯一性,所以单例可以继承MonoBehaviour,所以也就自带了Unity的生命周期,比如Start,Awake,Update等等,而且也支持在编辑器面板的一些公共可视化参数编辑,而静态类由于其本身不能继承的特性,也就失去了这个优势,所有的这些都需要自己去实现,就好比图2中的transform,图1里是可以直接使用本身的transform,因为继承了MonoBehaviour自带了这个对象,但是自己写的静态类就需要自己写一个方法从外部传进来了。静态类本身的静态属性让其本身就是唯一的,所以也不需要像单例模式那样自己去保证唯一性。
  2. 静态类中的成员会一直存在直到应用退出。静态类中的成员引用指针或者值对象都会一直存在,直到你退出应用,而单例管理类是可以随着切换场景销毁的,就比如你单例类的脚本挂在一个Gameobject上,那么你Destroy了这个Gameobject之后,这个单例也就被销毁掉了,单例里的所有成员,引用指针,都会被销毁,等待GC回收掉,而在我们平时做游戏的时候,当然不希望在场景1使用的某些管理类,比如只有场景一才需要的子弹管理器,到了场景二还存在,因为可能我们场景二完全就不是一个战斗场景,不需要子弹,那如果这个管理器还保留着,缓存着那些子弹,不就是浪费了内存么,因为我们根本不需要,所以一般在场景切换的时候,我们就可以根据需求,去销毁释放一些下一个场景并不需要的单例类,而静态类本身无法被销毁,自然就达不到我们的目的了。
分析完以上两点,那么是不是游戏中静态类就没有用武之地了呢?其实也不是,我就发现了一个地方,如果用静态类来管理,就非常合适,那就是存档。
  • 静态类适用场景:游戏存档 (单机类轻量级游戏适用,3A大作的那种存档数据量巨大的应该会有其他方案吧,有大佬知道的希望可以在评论区讨教一下) 因为游戏存档是所有地方都需要调用和使用的,那么其实可以用静态类来做管理,读取和保存,我感觉用着还是很方便的,你不需要去操心切换场景是不是要销毁释放,因为存档是一直存在在游戏中的,你随时都需要用来读或者存,尤其是做轻量级单机小游戏,下面我就简单的写一个存档的静态类管理,使用的是Unity自带的PlayerPref类。 顺手把实际用的地方也写一下
这次的分享到这里就差不多了,希望能帮助到大家,如果觉得对你有帮助的话欢迎关注我以及在下方留言,让我知道你们的想法,如果文中有任何说的不对的地方也欢迎各位大佬在评论区留言,我定会马上改正,先在这里谢谢大家了!
<think>好的,我现在需要解决用户的问题:在QML中使用C++实现全局类,并通过CMake进行构建。用户想知道如何在QML中注册并使用这个类,以及配置CMake。让我先理清步骤。 首先,用户提到了模式。在C++中,通常通过静态成员函数返回静态实来实现,确保只有一个实存在。接下来,需要将这个类注册到QML中,以便在QML中访问。根据之前的引用,使用QML_ELEMENT或相关宏来注册类型是关键。用户之前的问题涉及QMLC++的集成,所以可能需要参考这些方法。 然后,CMake的配置。根据引用[3][4],创建可重用的QML模块需要正确配置CMakeLists.txt,特别是生成QML类型注册信息。可能需要使用qt_add_qml_module或者相关的CMake命令来注册类型。接下来,我需要确保类被正确导出到QML。可能需要使用QML_SINGLETON宏,或者通过qmlRegisterSingletonType函数来注册。根据引用[4],QML_ELEMENT宏可以用于注册类,但如果是,可能需要额外的步骤,比如在注册时指定特性。 另外,头文件需要包含必要的宏QML的注册头文件,比如#include<QtQml/qqmlregistration.h>。同时,在CMake中,需要确保生成元对象系统文件,这可能涉及到AUTOMOC的设置,以及添加Qt相关的模块依赖,如QmlQuick。 可能的步骤分解: 1.创建C++类,确保有Q_OBJECT宏QML注册宏。2.在类中使用QML_SINGLETON或相应宏声明。3.配置CMakeLists.txt,使用qt_add_qml_module或其他命令来注册类型。4.在QML中导入模块并使用对象。 需要注意的地方:的注册方式是否正确,CMake配置是否生成必要的元信息,以及QML中导入的模块路径是否正确。可能需要参考Qt文档中关于注册的部分,确保使用正确的方法。如,使用qmlRegisterSingletonType来注册,或者在QML_ELEMENT宏的基础上添加属性。 此外,用户提到使用CMake,所以需要确保CMake配置中包括Qt的Qml模块,并且正确设置插件的生成。引用[3]中的子可能有用,特别是关于创建库的部分,可能需要将类作为库的一部分构建,并在QML模块中导出。 现在需要验证这些步骤是否正确,是否有遗漏。如,类的实现是否必须继承自QObject,是否需要在注册时指定类型,CMake中是否需要特别的指令来处理注册。可能需要查阅Qt的文档,确认最新的注册方法,比如在Qt6中是否推荐使用QML_SINGLETON宏配合QML_ELEMENT。 总结步骤: -创建类,使用QML_ELEMENTQML_SINGLETON宏。-在CMake中配置qt_add_qml_module,指定类型。-在QML中导入并使用。</think>### 在QML中注册并使用C++全局类的实现步骤 #### 一、创建C++类 1. **定义类**(需继承`QObject`并添加元对象支持): ```cpp // MySingleton.h #pragma once #include <QObject> #include <QtQml/qqmlregistration.h> class MySingleton : public QObject { Q_OBJECT QML_ELEMENT QML_SINGLETON // 关键:声明为类型 public: static MySingleton* instance(); Q_INVOKABLE void doSomething(); private: explicit MySingleton(QObject* parent = nullptr); }; ``` 2. **实现逻辑**: ```cpp // MySingleton.cpp #include "MySingleton.h" MySingleton* MySingleton::instance() { static MySingleton instance; return &instance; } MySingleton::MySingleton(QObject* parent) : QObject(parent) {} void MySingleton::doSomething() { qDebug() << "Singleton method called"; } ``` #### 二、配置CMake构建系统 1. **项目根目录的`CMakeLists.txt`**: ```cmake cmake_minimum_required(VERSION 3.16) project(MyQmlProject) set(CMAKE_AUTOMOC ON) find_package(Qt6 REQUIRED COMPONENTS Core Qml Quick) # 定义QML模块 qt_add_qml_module(myapp URI MyApp # QML模块的导入路径 VERSION 1.0 SINGLETON_TYPES MySingleton # 关键:注册类型 SOURCES src/MySingleton.h src/MySingleton.cpp ) ``` 2. **模块目录结构**: ``` ├── CMakeLists.txt └── src/ ├── MySingleton.h └── MySingleton.cpp ``` #### 三、在QML中使用 ```qml // Main.qml import QtQuick import MyApp 1.0 // 对应CMake中定义的URI Item { Component.onCompleted: { MySingleton.doSomething() // 直接访问方法 } } ``` #### 四、关键配置说明 1. **`QML_SINGLETON`宏**:标记该类为QML类型,允许通过类型名直接访问[^4]。 2. **`qt_add_qml_module`中的`SINGLETON_TYPES`**:在CMake中声明类型,确保生成正确的QML元类型信息[^3]。 3. **URI匹配规则**:QML导入路径`MyApp 1.0`需与CMake中`URI`字段完全一致[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值