(十)C++自制植物大战僵尸游戏设置功能实现

news2024/9/20 16:54:31

植物大战僵尸游戏开发教程专栏地址icon-default.png?t=N7T8http://t.csdnimg.cn/m0EtD


游戏设置

游戏设置功能是一个允许玩家根据个人喜好和设备性能来调整游戏各项参数的重要工具。游戏设置功能是为了让玩家能够根据自己的需求和设备性能来调整游戏,以获得最佳的游戏体验。不同的游戏和平台可能具有不同的设置选项和特点,玩家可以根据自己的喜好和需求进行选择和调整。

  • 基础设置:玩家可以根据自己的习惯选择开启或关闭某些功能。
  • 帧率:决定游戏的流畅度,高帧率通常意味着更流畅的游戏体验,但也可能增加设备的负担。
  • 分辨率:影响游戏的清晰度,高分辨率可以提供更细腻的画面,但同样可能增加设备的运算压力。
  • 音乐音效设置:可以调整音乐音效播放的音量。
  • 布局设置:允许玩家自定义游戏界面上的各种元素布局,如小地图、坦克信息等,以满足不同玩家的操作习惯。

代码文件位置

游戏设置相关的代码文件存放在Class\Scenes\MainMenuScene文件夹中,详细位置如下图所示。


OptionsScene.h 

在头文件中定义了两个枚举类OptionScene_CheckBoxOptionScene_SliderOptionScene_CheckBox枚举类定义了游戏相关设置,玩家可以自定义这些设置,使用复选框实现。OptionScene_Slider枚举类定义背景音乐和音效,玩家可以分别调整其音量大小和开关,使用滑动条实现。

enum class OptionScene_CheckBox
{
	显示信息 = 1,
	全屏,
	高帧率,
	鼠标隐藏,
	拉伸显示,
	缓入动画,
	垂直同步
};

enum class OptionScene_Slider
{
	音乐 = 1,
	音效
};

在头文件中定义了OptionsMenu类用于创建游戏中的设置菜单。它继承Dialog,所以游戏设置通过对话框来实现,用户在游戏场景中可以选择直接弹出对游戏进行设置。

class OptionsMenu :public Dialog
{
public:
	CREATE_FUNC(OptionsMenu);
	
CC_CONSTRUCTOR_ACCESS:
	OptionsMenu();
	~OptionsMenu();
	virtual bool init() override;
	
protected:
	virtual void createDialog();                                                                                      /* 创建对话框 */
	virtual CheckBox* createCheckBox(Vec2&, Vec2&, const std::string&, OptionScene_CheckBox, const std::string,
		const std::string, const bool IsNew = false);                                                                 /* 创建复选框 */
	virtual ControlSlider* createSlider(Vec2&, Vec2&, const std::string&, OptionScene_Slider, Sprite*, Sprite*,
		Sprite*, Sprite* = nullptr, const bool IsNew = false);                                                        /* 创建滑动条 */
	virtual void deleteDialog() override;                                                                             /* 删除对话框 */

private:
	void createButton();
	void backGroundMusicVolumeChangeCallBack(Ref* sender, Control::EventType type);                                  /* 背景音乐音量调节回调函数*/
	void soundEffectMusicVolumeChangeCallBack(Ref* sender, Control::EventType type);                                 /* 音效音乐音量调节回调函数*/

protected:
	Sprite* _option;         /* 对话框 */
	Director* _director;

private:
	UserDefault* _userDefault;
};

OptionsScene.cpp

init()函数

创建游戏设置菜单,首先会调用init函数。在init函数中首先会在场景中创建一个黑色半透明的遮罩层,使用场景变黑,让玩家聚焦到设置菜单上。然后使用createShieldLayer(this)函数屏蔽除本层之外的所以事件监听,作用是让玩家只能和设置菜单进行交互。最后使用createDialog()函数创建游戏菜单。

bool OptionsMenu::init()
{
	if (!LayerColor::initWithColor(Color4B(0, 0, 0, 180)))return false;

	createShieldLayer(this);

	this->createDialog();

	return true;
}

createDialog()函数

void OptionsMenu::createDialog()
{
	_option = Sprite::createWithSpriteFrameName("options_menuback.png");
	_option->setPosition(_director->getWinSize() / 2);
	_option->setScale(1.7f);
	_option->setName("_option");
	this->addChild(_option);
	
	/* 触摸移动监听 */
	createTouchtListener(_option);

	/* 创建滑动条 */
	this->createSlider(Vec2(250, 350), Vec2(140, 350), _global->userInformation->getGameText().find("音乐")->second, OptionScene_Slider::音乐,
		Sprite::createWithSpriteFrameName("options_sliderslot.png"),
		Sprite::createWithSpriteFrameName("options_sliderslot.png"),
		Sprite::createWithSpriteFrameName("options_sliderknob2.png"),
		Sprite::createWithSpriteFrameName("options_sliderknob2.png"));
	this->createSlider(Vec2(250, 310), Vec2(140, 310), _global->userInformation->getGameText().find("音效")->second, OptionScene_Slider::音效, 
		Sprite::createWithSpriteFrameName("options_sliderslot.png"),
		Sprite::createWithSpriteFrameName("options_sliderslot.png"),
		Sprite::createWithSpriteFrameName("options_sliderknob2.png"),
		Sprite::createWithSpriteFrameName("options_sliderknob2.png"));

	/* 创建复选框 */
	this->createCheckBox(Vec2(300, 280), Vec2(140, 280), _global->userInformation->getGameText().find("信息")->second, OptionScene_CheckBox::显示信息, "options_checkbox0", "options_checkbox1");
	this->createCheckBox(Vec2(300, 245), Vec2(140, 245), _global->userInformation->getGameText().find("全屏")->second, OptionScene_CheckBox::全屏, "options_checkbox0", "options_checkbox1");
	this->createCheckBox(Vec2(300, 210), Vec2(140, 210), _global->userInformation->getGameText().find("高帧率")->second, OptionScene_CheckBox::高帧率, "options_checkbox0", "options_checkbox1");
	this->createCheckBox(Vec2(300, 175), Vec2(140, 175), _global->userInformation->getGameText().find("拉伸显示")->second, OptionScene_CheckBox::拉伸显示, "options_checkbox0", "options_checkbox1");

    /* 创建按钮 */
	this->createButton();
}

创建设置菜单背景图,并设置屏幕中心位置,设置缩放1.7倍大小,如下代码。 

_option = Sprite::createWithSpriteFrameName("options_menuback.png");
_option->setPosition(_director->getWinSize() / 2);
_option->setScale(1.7f);
_option->setName("_option");
this->addChild(_option);

触摸监听已创建的菜单背景图,只有加入触摸监听才能对设置菜单进行拖动。 createTouchtListener()函数实现请查看上一篇教程自定义对话框。

/* 触摸移动监听 */
createTouchtListener(_option);

下方代码创建了两个滑动条和四个复选框,滑动条用于控制音效、背景音乐的音量,复选框可以设置游戏是否全屏显示、是否高帧率、是否将画面铺满屏幕等操作。

/* 创建滑动条 */
this->createSlider(Vec2(250, 350), Vec2(140, 350), _global->userInformation->getGameText().find("音乐")->second, OptionScene_Slider::音乐,
		Sprite::createWithSpriteFrameName("options_sliderslot.png"),
		Sprite::createWithSpriteFrameName("options_sliderslot.png"),
		Sprite::createWithSpriteFrameName("options_sliderknob2.png"),
		Sprite::createWithSpriteFrameName("options_sliderknob2.png"));
this->createSlider(Vec2(250, 310), Vec2(140, 310), _global->userInformation->getGameText().find("音效")->second, OptionScene_Slider::音效, 
		Sprite::createWithSpriteFrameName("options_sliderslot.png"),
		Sprite::createWithSpriteFrameName("options_sliderslot.png"),
		Sprite::createWithSpriteFrameName("options_sliderknob2.png"),
		Sprite::createWithSpriteFrameName("options_sliderknob2.png"));

	/* 创建复选框 */
this->createCheckBox(Vec2(300, 280), Vec2(140, 280), _global->userInformation->getGameText().find("信息")->second, OptionScene_CheckBox::显示信息, "options_checkbox0", "options_checkbox1");
this->createCheckBox(Vec2(300, 245), Vec2(140, 245), _global->userInformation->getGameText().find("全屏")->second, OptionScene_CheckBox::全屏, "options_checkbox0", "options_checkbox1");
this->createCheckBox(Vec2(300, 210), Vec2(140, 210), _global->userInformation->getGameText().find("高帧率")->second, OptionScene_CheckBox::高帧率, "options_checkbox0", "options_checkbox1");
this->createCheckBox(Vec2(300, 175), Vec2(140, 175), _global->userInformation->getGameText().find("拉伸显示")->second, OptionScene_CheckBox::拉伸显示, "options_checkbox0", "options_checkbox1");

createSlider()函数

使用Cocos2d-xControlSlider UI控件创建滑动条,并且设置滑动条的最大最小值,设置位置,根据传入参数slider_type调用不同的回调函数,在回调函数中对音乐或音效的音量进行调整。

函数传入参数较多。

vec2:滑动条位置;

Label:滑动条名称;

slider_type:枚举类,在头文件中定义,音乐或音效;

BgFile、progressFile、thumbFile、selectthumbFile:滑动条组成的三部分,分别是背景图、显示进度图以及可拖动按钮图。thumbFile、selectthumbFile的区别是一个是正常显示图,另一个是按下或选中后显示图;

ControlSlider* OptionsMenu::createSlider(Vec2& vec2, const std::string& Label, OptionScene_Slider slider_type,
	Sprite* BgFile, Sprite* progressFile, Sprite* thumbFile, Sprite* selectthumbFile)
{
	/* 创建滑动条 */
	ControlSlider* slider; ;
	selectthumbFile ? selectthumbFile->setColor(Color3B::GRAY),
		slider = ControlSlider::create(BgFile, progressFile, thumbFile, selectthumbFile) :
		slider = ControlSlider::create(BgFile, progressFile, thumbFile);

	slider->setMinimumValue(0);
	slider->setMaximumValue(100);
	slider->setPosition(vec2);
	_option->addChild(slider);

	switch (slider_type)
	{
	case OptionScene_Slider::音乐:
		slider->setValue(_global->userInformation->getBackGroundMusicVolume() * 100);
		slider->addTargetWithActionForControlEvents(this, cccontrol_selector(OptionsMenu::backGroundMusicVolumeChangeCallBack), Control::EventType::VALUE_CHANGED);
		break;
	case OptionScene_Slider::音效:
		slider->setValue(_global->userInformation->getSoundEffectVolume() * 100);
		slider->addTargetWithActionForControlEvents(this, cccontrol_selector(OptionsMenu::soundEffectMusicVolumeChangeCallBack), Control::EventType::VALUE_CHANGED);
		break;
	}
	return slider;
}

createCheckBox()函数

函数参数较多。

vec2:复选框的位置;

Label:复选框名称;

button_type:枚举类,在头文件中定义,表示按钮类型;

NotSelect、Select:复选框组成部分,分别是没有选中和选中后的按钮图样式;

CheckBox* OptionsMenu::createCheckBox(Vec2 &vec2, const std::string &Label, OptionScene_CheckBox button_type, const std::string NotSelect, const std::string Select)
{
	auto checkbox = CheckBox::create();
	checkbox->loadTextureBackGround(NotSelect + ".png", TextureResType::PLIST);
	checkbox->loadTextureFrontCross(Select + ".png", TextureResType::PLIST);
	checkbox->setPosition(vec2);
	_option->addChild(checkbox);
	
	checkbox->addEventListener([=](Ref* sender, CheckBox::EventType type)
	{
		switch (type)
		{
		case CheckBox::EventType::SELECTED:
			switch (button_type)
			{
			case OptionScene_CheckBox::显示信息: /* 显示信息 */
				_userDefault->setBoolForKey("SHOWINFORMATION", true);
				_global->userInformation->setIsShowInformation(CheckBox::EventType::SELECTED); /* 更新 */
				_director->setDisplayStats(true);
				break;
			case OptionScene_CheckBox::全屏: /* 全屏 */
				_userDefault->setBoolForKey("SHOWFULLSCREEN", true);
				_global->userInformation->setIsSelectFullScreen(CheckBox::EventType::SELECTED);
				((GLViewImpl*)_director->getOpenGLView())->setFullscreen();
				break;
			case OptionScene_CheckBox::高帧率: /* 高帧率 */
				_userDefault->setBoolForKey("SHOWHIGHFPS", true);
				_global->userInformation->setIsSelectHighFPS(CheckBox::EventType::SELECTED);
				_director->setAnimationInterval(1.0f / UserInformation::getScreenDisplayFrequency());
				break;
			case OptionScene_CheckBox::鼠标隐藏: /* 鼠标隐藏 */
				UserData::getInstance()->caveUserData("CURSORHIDE", true);
				_global->userInformation->setIsSelectCursorNotHide(CheckBox::EventType::SELECTED);
				break;
			case OptionScene_CheckBox::拉伸显示: /* 拉伸显示 */
				_userDefault->setBoolForKey("STRETCHINGSHOW", true);
				_director->getOpenGLView()->setDesignResolutionSize(_director->getWinSize().width, _director->getWinSize().height, ResolutionPolicy::EXACT_FIT);
				_global->userInformation->setIsSelectStretchingShow(CheckBox::EventType::SELECTED);
				break;
			case OptionScene_CheckBox::缓入动画: 
				UserData::getInstance()->caveUserData("EASEANIMATION", true);
				_global->userInformation->setIsEaseAnimation(CheckBox::EventType::SELECTED);
				break;
			case OptionScene_CheckBox::垂直同步:
				_userDefault->setBoolForKey("VERTICALSYNCHRONIZATION", true);
				wglSwapIntervalEXT(1);
				_global->userInformation->setIsVerticalSynchronization(CheckBox::EventType::SELECTED);
				break;
			default:
				break;
			}
			break; 
		case CheckBox::EventType::UNSELECTED:
			switch (button_type)
			{
			case OptionScene_CheckBox::显示信息:
				_userDefault->setBoolForKey("SHOWINFORMATION", false);
				_global->userInformation->setIsShowInformation(CheckBox::EventType::UNSELECTED); /* 更新 */
				_director->setDisplayStats(false);
				break;
			case OptionScene_CheckBox::全屏:
				_userDefault->setBoolForKey("SHOWFULLSCREEN", false);
				_global->userInformation->setIsSelectFullScreen(CheckBox::EventType::UNSELECTED);
				((GLViewImpl*)_director->getOpenGLView())->setWindowed(1280, 720);
				break;
			case OptionScene_CheckBox::高帧率:
				_userDefault->setBoolForKey("SHOWHIGHFPS", false);
				_global->userInformation->setIsSelectHighFPS(CheckBox::EventType::UNSELECTED);
				_director->setAnimationInterval(1.0f / 30);
				break;
			case OptionScene_CheckBox::鼠标隐藏:
				UserData::getInstance()->caveUserData("CURSORHIDE", false);
				_global->userInformation->setIsSelectCursorNotHide(CheckBox::EventType::UNSELECTED);
				break;
			case OptionScene_CheckBox::拉伸显示:
				_userDefault->setBoolForKey("STRETCHINGSHOW", false);
				_director->getOpenGLView()->setDesignResolutionSize(_director->getWinSize().width, _director->getWinSize().height, ResolutionPolicy::SHOW_ALL);
				_global->userInformation->setIsSelectStretchingShow(CheckBox::EventType::UNSELECTED);
				break;
			case OptionScene_CheckBox::缓入动画:
				UserData::getInstance()->caveUserData("EASEANIMATION", false);
				_global->userInformation->setIsEaseAnimation(CheckBox::EventType::UNSELECTED);
				break;
			case OptionScene_CheckBox::垂直同步:
				_userDefault->setBoolForKey("VERTICALSYNCHRONIZATION", false);
				wglSwapIntervalEXT(0);
				_global->userInformation->setIsVerticalSynchronization(CheckBox::EventType::UNSELECTED);
				break;
			default:
				break;
			}
			break;
		default:
			break;
		}
	});

	return checkbox;
}

backGroundMusicVolumeChangeCallBack()函数

背景音乐音量调整的回调函数,当拖动背景音乐滑动条时,会自动触发该函数。循环遍历所有背景音乐调整其播放音量。此外将音量数值记录到存档之中,之后启动游戏不需要再次调整。

void OptionsMenu::backGroundMusicVolumeChangeCallBack(Ref* sender, Control::EventType type)
{
	auto slider = (ControlSlider*)sender;
	for (auto sp : _global->userInformation->getBackgroundMusic())  /* 循环设置音乐音量 */
	{
		AudioEngine::setVolume(sp, slider->getValue() / 100.0f);
	}

	_global->userInformation->setBackGroundMusicVolume(slider->getValue() / 100.0f);
	_userDefault->setFloatForKey("GLOBALMUSIC", _global->userInformation->getBackGroundMusicVolume());

	if (slider->getSelectedThumbSprite()->getContentSize().height > 30)
	{
		/* 旋转动画 */
		slider->getThumbSprite()->setRotation(slider->getValue() * 10);
		slider->getSelectedThumbSprite()->setRotation(slider->getValue() * 10);
	}
}

soundEffectMusicVolumeChangeCallBack()函数

音效音量调整回调函数,当拖动音效的滑动条时,会自动触发该函数。将音量数值记录到存档之中,之后启动游戏不需要再次调整。

void OptionsMenu::soundEffectMusicVolumeChangeCallBack(Ref* sender, Control::EventType type)
{
	/* 设置音效音量 */
	auto slider = (ControlSlider*)sender;
	_global->userInformation->setSoundEffectVolume(slider->getValue() / 100.0f);
	_userDefault->setFloatForKey("SOUNDEFFECT", _global->userInformation->getSoundEffectVolume());

	if (slider->getSelectedThumbSprite()->getContentSize().height > 30)
	{
		/* 旋转动画 */
		slider->getThumbSprite()->setRotation(slider->getValue() * 10);
		slider->getSelectedThumbSprite()->setRotation(slider->getValue() * 10);
	}
}

其他函数不再一一列举,请自行查看。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1597425.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

相机系列——透视投影:针孔相机模型

作者:木一 引言 上文我们提到,三维相机是对真实世界成像的模拟,为了让三维物体在计算机屏幕上呈现出来的图像符合人眼观察效果,通常采用透视投影方式模拟相机成像,为了简化计算,可以用针孔相机模型来描述…

设计模式——观察者模式17

观察者模式指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式。 中介者模式是N对N的双向关系。观察者模式是1对N的单向关系。 设计模式,一定要敲代码…

STC89C52学习笔记(十三)

STC89C52学习笔记(十三) 综述:本文讲述了红外调控的原理和通信以及外部中断相关知识。 一、红外调控 1、定义 红外遥控是利用红光进行通信的设备。 2、特点 ①由红LED将调制后的信号发出,由专门的红外接收头进行解调输出。 …

​​​​网络编程探索系列之——广播原理剖析

hello !大家好呀! 欢迎大家来到我的网络编程系列之广播原理剖析,在这篇文章中, 你将会学习到如何在网络编程中利用广播来与局域网内加入某个特定广播组的主机! 希望这篇文章能对你有所帮助,大家要是觉得我写…

jupyter使用虚拟环境里的依赖配置

进入虚拟环境fourier-features-pytorchconda activate fourier-features-pytorch 安装ipykernel pip install ipykernel -i https://pypi.tuna.tsinghua.edu.cn/simple将核与虚拟环境匹配 python -m ipykernel install --user --namefourier-features-pytorch打开jupyter j…

Kafka 架构深入介绍 及搭建Filebeat+Kafka+ELK

目录 一 架构深入介绍 (一)Kafka 工作流程及文件存储机制 (二)数据可靠性保证 (三)数据一致性问题 (四)故障问题 (五)ack 应答机制 二 实…

【max材质addtive叠加模式特效渲染不出通道的解决办法】

max材质addtive叠加模式特效渲染不出通道的解决办法 2021-12-22 18:15 max的scanline扫描线,vray渲染可以,红移不行(只支持它自己的材质,它自己的材质没有additive模式)。据说mr是可以的。 右侧的球体使用附加不透明度。 附加不透明度通过将…

关于机器学习/深度学习的一些事-答知乎问(六)

如何使用频率域变换对序列数据进行增强? 时频变换是常见的信号分析思路,同样可用于数据增强。在频率域添加噪声是方法之一。比如可以对传感器信号应用短时傅里叶变换STFT得到具有时序关系的谱特征,再在谱特征上应用两种数据增强方法。一是对…

Amazon MemoryDB for Redis的探索和实践

一、背景 由于当下项目的日益增长的数据量,单机Redis已经远远不能满足我们的要求。考虑转成集群,但是直接在服务器中搭建Redis集群的话,EC2挂掉则Redis也会随之挂掉,耦合性太强。所以将Redis相关的服务全部抽取在单独的服务器上或…

论文笔记:Time Travel in LLMs: Tracing Data Contamination in Large Language Models

iclr 2024 spotlight reviewer评分 688 1 intro 论文认为许多下游任务(例如,总结、自然语言推理、文本分类)上观察到的LLMs印象深刻的表现可能因数据污染而被夸大 所谓数据污染,即这些下游任务的测试数据出现在LLMs的预训练数据…

ins视频批量下载,instagram批量爬取视频信息

简介 Instagram 是目前最热门的社交媒体平台之一,拥有大量优质的视频内容。但是要逐一下载这些视频往往非常耗时。在这篇文章中,我们将介绍如何使用 Python 编写一个脚本,来实现 Instagram 视频的批量下载和信息爬取。 我们使用selenium获取目标用户的 HTML 源代码,并将其保存…

MySQL模糊查询

一、MySQL通配符模糊查询(%,_) 1.1.通配符的分类 1.“%”百分号通配符:表示任何字符出现任意次数(可以是0次) 2.“_”下划线通配符:表示只能匹配单个字符,不能多也不能少,就是一个字符。当然…

计算机组成原理【CO】Ch3 存储系统

文章目录 考纲3.1 存储系统概述3.2 主存储器3.3 主存储器与CPU的连接3.4 外部存储器3.5 高速缓冲存储器3.6 虚拟存储器【※】存储系统总体流程图【※】各个部件的存储位置计算机存储相关硬件与数据结构说明进程控制块(PCB)页表页表始址页表始址寄存器(PTR)MMU(内存管理单元…

Springboot Gateway 报错Failed to resolve “bogon”的原因及解决办法

一、问题出现原因及初步分析 今天遇到一个奇怪的错误,一个一直正确运行的微服务后台,突然无法访问,如何重启都会报错。 想到近期有人在服务器上安装过其它服务,因此,考虑可能是配置问题,可配置问题修复后…

实时数据同步之Maxwell和Canal

文章目录 一、概述1、实时同步工具概述1.1 Maxwell 概述1.2 Canal概述 2、数据同步工作原理2.1 MySQL 主从复制过程2.2 两种工具工作原理 3、MySQL 的 binlog详解3.1 什么是 binlog3.2 binlog 的开启3.3 binlog 的分类设置 4、Maxwell和Canal对比5、环境安装 二、Maxwell 使用1…

信也科技网络自动化实践-网络策略管理

1、背景 随着各种法律法规和行业标准的出台和更新,企业或组织需要遵守各种安全合规性要求。网络安全策略管理需要符合这些要求,从而保障企业或组织的安全和合规性。网络安全策略管理需要涵盖企业或组织的整个网络生命周期,包括网络规划、设计…

halcon 3.2标定相机

参考《solution_guide_iii_c_3d_vision.pdf》 3.2.2.2 Which Distortion Model to Use 选用何种畸变模型 对于面阵相机,halcon中两种畸变模型:The division model and the polynomial model(差分模型和多项式模型),前…

MLOps

参考: 什么是MLOps?与DevOps有何异同?有什么价值?https://baijiahao.baidu.com/s?id1765071998288593530&wfrspider&forpcMLOps简介_AI开发平台ModelArts_WorkflowMLOps(Machine Learning Operation)是机器学习&#xf…

kafka(六)——存储策略

存储机制 kafka通过topic作为主题缓存数据,一个topic主题可以包括多个partition,每个partition是一个有序的队列,同一个topic的不同partiton可以分配在不同的broker(kafka服务器)。 关系图 partition分布图 名称为t…

Unity 扩展自定义编辑器窗口

在Assets文件夹路径下任意位置创建Editor文件夹,将扩展编辑器的代码放在Editor文件夹下 生成编辑器窗口 代码中首先引用命名空间 using UnityEditor; 然后将创建的类继承自EditorWindow public class MenuEditor : EditorWindow 然后通过扩展编辑器菜单功能调用…