【Unity】RPG2D龙城纷争(六)关卡编辑器之角色编辑

更新日期:2024年6月26日。
项目源码:第五章发布(正式开始游戏逻辑的章节)

索引

  • 简介
    • 一、角色编辑模式
      • 1.将字段限制为只读
      • 2.创建角色(刷角色)
      • 3.预览所有角色
      • 4.编辑选中角色属性
      • 5.移动角色位置
      • 6.移除角色

简介

上一篇完成的关卡编辑器已支持创建关卡环境(主要由地块单元组成),本篇,在关卡环境的基础上,需要完成角色编辑、要诀编辑等功能(角色编辑模式)。

一、角色编辑模式

1.将字段限制为只读

在开始角色编辑模式之前,我们对角色(Role)地块(Block)类定义的字段进行一些改进,为一些字段添加ReadOnly特性标记:

    public class Role : HTBehaviour{/// <summary>/// 角色头像/// </summary>[Label("角色头像"), ReadOnly] public Sprite HeadImage;//其他省略......}public class Block : HTBehaviour{/// <summary>/// 类型/// </summary>[Label("类型"), ReadOnly] public BlockType Type;//其他省略......}

ReadOnly使得该字段为只读的,在检视器面板上不可编辑。

在这里插入图片描述

这样做的目的是防止这些属性被不小心篡改,因为他们都将交由关卡编辑器来权衡设置。

当然你也可以不这样做,只需去掉ReadOnly标记即可。

2.创建角色(刷角色)

试想一下角色编辑的功能该如何展现,第一步必然是能够创建角色,在这里我们想像刷地块一样,鼠标停留到一个位置,直接就能在该位置刷出一个角色。

那么,着手开干:

        /// <summary>/// 是否激活角色刷子/// </summary>private bool _isActiveRoleBrush = false;/// <summary>/// 角色刷子类型名称/// </summary>private string[] _roleBrushTypeName = new string[] { "玩家", "敌人" };/// <summary>/// 角色刷子类型(刷出来的角色属于此阵营)/// </summary>private RoleCamp _roleBrushType = RoleCamp.Player;/// <summary>/// 角色刷子数据集(刷出来的角色使用此数据集)/// </summary>private RoleDataSet _roleDataSet;/// <summary>/// 创建一个角色/// </summary>/// <param name="block">角色所在地块</param>/// <param name="dataSet">角色数据集</param>private void CreateRole(Block block, RoleDataSet dataSet){//通过角色模板 _roleTmp 创建一个新角色GameObject obj = PrefabUtility.InstantiatePrefab(_roleTmp) as GameObject;obj.name = "Role";obj.transform.SetParent(_level.RolesRoot);obj.transform.localPosition = new Vector3(block.transform.position.x, block.transform.position.y, -1);obj.transform.localRotation = Quaternion.identity;obj.transform.localScale = Vector3.one;obj.SetActive(true);//为角色生成一个随机ID,并应用刷子类型(角色阵营),这里类似刷地块的逻辑Role role = obj.GetComponent<Role>();role.ID = Guid.NewGuid().ToString();role.Name = dataSet.name;role.Camp = _roleBrushType;//设置角色数据集role.SetDataSet(dataSet);_roles.Add(role);//与地块建立关联role.StayBlock = block;block.StayRole = role;EditorUtility.SetDirty(role);EditorUtility.SetDirty(block);Selection.activeGameObject = obj;}

如上,完成了创建角色的方法,再通过刷子相关的控制变量,实现UI控件面板后:

在这里插入图片描述

要实现按1键开刷的功能,依然是在OnSceneGui方法中补充代码:

        private void OnSceneGui(SceneView sceneView){if (Event.current == null)return;if (_editMode == EditMode.Map && _isActiveMapBrush){//地块编辑模式}else if (_editMode == EditMode.Role && _isActiveRoleBrush && _roleDataSet != null){if (Event.current.isKey && Event.current.keyCode == KeyCode.Alpha1 && Event.current.type == EventType.KeyDown){//将Scene视图坐标转换为世界坐标Vector2 pos = ScreenToWorldPointInScene(sceneView.camera, Event.current.mousePosition);//获取坐标位置的地块Block block = GetBlockByPoint(pos);if (block){//必须该地块不存在角色if (block.StayRole == null){//才在该地块创建一个角色CreateRole(block, _roleDataSet);}}}EditorGUIUtility.AddCursorRect(sceneView.position, MouseCursor.SlideArrow);}}

此时,我们便可以创建一个角色数据集,然后开刷了:

在这里插入图片描述

不过,刚刷出来的角色是没有头像的,这里显示为红色是因为他所属敌方阵营

而且,角色头像前面已经被我们搞成ReadOnly了,这里也修改不了啊(检视器面板只能看),所以,迫切需要在关卡编辑器中实现对这一个个灰色属性的编辑功能。

3.预览所有角色

首先,为了能全局预览场景中的所有角色,我们先将所有角色按阵营进行分类展示:

        /// <summary>/// 玩家角色数量/// </summary>private int _playerNum;/// <summary>/// 敌人角色数量/// </summary>private int _enemyNum;/// <summary>/// 当前选中的角色物体/// </summary>private GameObject _currentSelectRoleObj;/// <summary>/// 当前选中的角色/// </summary>private Role _currentSelectRole;/// <summary>/// 是否显示所有玩家角色/// </summary>private bool _isShowPlayer = false;/// <summary>/// 是否显示所有敌人角色/// </summary>private bool _isShowEnemy = false;

通过加入上面的控制代码,然后再结合UI控件代码,实现在2个区域(玩家、敌人阵营)分别预览所有角色(UI控件代码就不贴了,看看源码就一目了然):

在这里插入图片描述

4.编辑选中角色属性

我们规定同时只能选中一个角色,进而进入编辑此角色状态。

那么,当选中角色时(Scene视图中选中角色物体),角色会被赋予到_currentSelectRoleObj_currentSelectRole

Tip:为了避免重复GetComponent<Role>(),使用_currentSelectRole来缓存当前角色物体身上的Role组件。

        private void EditRoleGUI(){//如果Scene视图中选择的目标物体改变if (_currentSelectRoleObj != Selection.activeGameObject){//则尝试获取其上的Role组件_currentSelectRoleObj = Selection.activeGameObject;_currentSelectRole = _currentSelectRoleObj != null ? _currentSelectRoleObj.GetComponent<Role>() : null;}if (_currentSelectRole != null){//此时便选中了角色,在这里展示角色的相关属性,同时支持编辑}}

通过敲完繁琐的UI控件代码后,现在的编辑器界面便是这样:

在这里插入图片描述

在这里,我们可以重新赋予角色的数据集,以更换其内核。

赋予头像灰色头像(仅当角色禁用时展示),头像改变后,会立即体现在角色头像渲染器上:

在这里插入图片描述

角色的ID属性极其重要,在关卡间角色的属性继承存档读档剧情对话等一系列需要定位指定角色的功能,都是通过ID来确定的,所以ID不能重复,当然这里默认生成的Guid.NewGuid()是绝对不重复的。

只不过,为了方便后续关卡进行对应,主角的ID建议单独设置,比如某个主角ID为001,那么在所有关卡中,他的ID都必须为001

当我们把角色状态切换为Not Yet On Stage时,此角色将延时登场:

在这里插入图片描述

然后,下面列出了角色的8个要诀栏位对应的数据集,我们可以创建一系列要诀数据集,然后给每个角色都进行配置,4-8栏位会自动根据角色的等级进行激活,当然,也可以在后期使用要诀研习系统,为指定的角色学习任意要诀。

在这里插入图片描述

5.移动角色位置

如果我们想修改一个角色的位置,直接删了重新刷是一种笨办法,但因为角色的位置与其所处的地块存在直接关联,我们手动调节角色的位置自然是不可行的,所以需要实现控制角色移动的功能,比如:

        if (GUILayout.Button("上移", "ButtonLeft")){//保留角色所站的旧地块Block oldBlock = _currentSelectRole.StayBlock;//获取角色位置上方+1格的地块,为新地块Block newBlock = GetBlockByIndex(oldBlock.Pos + new Vector2Int(0, 1));if (newBlock != null && newBlock.StayRole == null){_currentSelectRole.transform.localPosition = new Vector3(newBlock.transform.position.x, newBlock.transform.position.y, -1);//交换新、旧地块的关联属性oldBlock.StayRole = null;_currentSelectRole.StayBlock = newBlock;newBlock.StayRole = _currentSelectRole;EditorUtility.SetDirty(oldBlock);EditorUtility.SetDirty(newBlock);EditorUtility.SetDirty(_currentSelectRole);}}

需要上、下、左、右移动功能,才能让角色可以变换到地图中的任意位置:

在这里插入图片描述

6.移除角色

同样的,自然需要移除角色的功能,我们在UI面板上已经画好了控件,只需实现对应的移除角色功能即可:

        /// <summary>/// 移除一个角色/// </summary>/// <param name="role">角色</param>private void RemoveRole(Role role){_roles.Remove(role);Block block = role.StayBlock;role.StayBlock = null;block.StayRole = null;//立即销毁角色物体DestroyImmediate(role.gameObject);EditorUtility.SetDirty(block);}

至此,角色编辑的功能便初步完成了,我们能够在关卡上任意布局角色编辑角色属性编辑角色要诀等,为后续驱动角色,进而驱动整个游戏逻辑打下了坚实的基础。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue中【事件修饰符号】详解

在Vue中&#xff0c;事件修饰符是一种特殊的后缀&#xff0c;用于修改事件触发时的默认行为。以下是Vue中常见的事件修饰符的详细解释&#xff1a; .stop 调用event.stopPropagation()&#xff0c;阻止事件冒泡。当你在嵌套元素中都有相同的事件监听器&#xff08;如click事件…

【Linux系统】进程替换 自主实现shell(简易版)

1.先看代码 && 现象 我们用exec*函数执行新的程序&#xff0c; exec*系列的函数&#xff0c;执行完毕后&#xff0c;后续的代码不见了&#xff0c;因为被替换了。 execl的返回值可以不关心了&#xff0c;只要替换成功&#xff0c;就不会向后继续运行&#xff0c;只要…

单片机是否有损坏,怎沫判断

目录 1、操作步骤&#xff1a; 2、单片机损坏常见原因&#xff1a; 3、 单片机不工作的原因&#xff1a; 参考&#xff1a;细讲寄存器读写与Bit位操作原理--单片机C语言编程Bit位的与或非屏蔽运算--洋桃电子大百科P019_哔哩哔哩_bilibili 1、操作步骤&#xff1a; 首先需要…

前置章节-熟悉Python、Numpy、SciPy和matplotlib

目录 一、编程环境-使用jupyter notebook 1.下载homebrew包管理工具 2.安装Python环境 3.安装jupyter 4.下载Anaconda使用conda 5.使用conda设置虚拟环境 二、学习Python基础 1.快排的Python实现 (1)列表推导-一种创建列表的简洁方式 (2)列表相加 2.基本数据类型及运…

Navicat上新啦

前言 Navicat&#xff0c;在数据库界&#xff0c;几乎是一个神奇的存在&#xff0c;似乎统治了数据库开发工具的“一片天”。且看下图&#xff1a; 红的蓝的绿的橙的…&#xff0c;可以说&#xff0c;留给它的color不多了。 那么商业BI到服务监控、从云托管到云协作&#xff…

最强文生图模型Stable Diffusion 3 Medium 正式开源

Stability AI 宣布 Stable Diffusion 3 Medium 现已开源&#xff0c;是 Stable Diffusion 3 系列中最新、最先进的文本生成图像 AI 模型 —— 官方声称是 “迄今为止最先进的开源模型”&#xff0c;其性能甚至超过了 Midjourney 6。 Stable Diffusion 3 Medium 模型规格参数达到…

【鸿蒙学习笔记】位置设置

官方文档&#xff1a;位置设置 目录标题 align&#xff1a;子元素的对齐方式direction&#xff1a;官方文档没懂&#xff0c;看图理解吧 align&#xff1a;子元素的对齐方式 Stack() {Text(TopStart)}.width(90%).height(50).backgroundColor(0xFFE4C4).align(Alignment.TopS…

Spring+Vue集成AOP系统日志

新建logs表 添加aop依赖 <!-- aop依赖--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId> </dependency> 新建获取ip地址工具类 import javax.servlet.http.H…

昇思25天学习打卡营第12天|ShuffleNet图像分类

1. 学习内容复盘 ShuffleNet网络介绍 ShuffleNetV1是旷视科技提出的一种计算高效的CNN模型&#xff0c;和MobileNet, SqueezeNet等一样主要应用在移动端&#xff0c;所以模型的设计目标就是利用有限的计算资源来达到最好的模型精度。ShuffleNetV1的设计核心是引入了两种操作&a…

自然语言处理:第三十八章: 开箱即用的SOTA时间序列大模型 -Timsfm

自然语言处理:第三十八章: 开箱即用的SOTA时间序列大模型 -Timsfm 文章链接:[2310.10688] A decoder-only foundation model for time-series forecasting (arxiv.org) 项目链接: google-research/timesfm: TimesFM (Time Series Foundation Model) is a pretrained time-ser…

【FFmpeg】avformat_alloc_output_context2函数

【FFmpeg】avformat_alloc_output_context2函数 1.avformat_alloc_output_context21.1 初始化AVFormatContext&#xff08;avformat_alloc_context&#xff09;1.2 格式猜测&#xff08;av_guess_format&#xff09;1.2.1 遍历可用的fmt&#xff08;av_muxer_iterate&#xff0…

C : 线性规划例题求解

Submit Page TestData Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 93 Solved: 49 Description 求解下述线性规划模型的最优值min &#xfffd;1&#xfffd;1&#xfffd;2&#xfffd;2&#xfffd;3&#xfffd;3&#xfffd;.&#xfffd;. &…

【SkiaSharp绘图13】SKCanvas方法详解(二)填充颜色、封装对象、高性能绘制、点(集)(多段)线、圆角矩形、Surface、沿路径绘制文字

文章目录 SKCanvas方法DrawColor 填充颜色DrawDrawable 绘制封装对象DrawImage 高性能绘制图像SKBitmap与SKImage对比DrawPicture 绘制图像SKPicture DrawPoint / DrawPoints 绘制点DrawRoundRect/DrawRoundRectDifference绘制圆角矩形DrawSurface 绘制SurfaceDrawTextOnPath沿…

Android - 利用 jitpack 免费发布闭源 aar

一、简述 目前(Android/java) library 的主要发布仓库有 MavenCentral 和 jitpack,我之前也对这两种仓库的发布流程做了详细介绍: 发布至 MavenCentral: https://juejin.cn/post/6953598441817636900发布至 jitpack: https://juejin.cn/post/7040733114506674183#heading-…

C# 入门—实现 Hello, World!

目录 一、.net 平台与.NET Framework框架 .NET Framework的构成 CLR&#xff1a;公共语言运行库 FCL&#xff1a;框架类库 WinForms ASP.NET ADO.NET WPF WCF WF LINQ Entity Framework Parallel LINQ 二、.net 能干什么 .net 两种交互模式 .net 能干什么 .net …

优化模型验证30:多车场车辆路径问题模型及Gurobipy验证

目录 1 数学模型 1.1 用到的符号集合 1.2 模型公式 2 模型验证代码 2.1 Gurobipy代码 2.2 结果可视化 多车场车辆路径问题的定义:大型的物流公司拥有多个车场,而每个车场都有若干车辆用于配送,决策者需要根据客户的所在位置,将客户分配到合适的车场和车辆中。 1 数学模…

c++静态成员变量和静态成员函数

1&#xff09;C入门级小知识&#xff0c;分享给将要学习或者正在学习C开发的同学。 2&#xff09;内容属于原创&#xff0c;若转载&#xff0c;请说明出处。 3&#xff09;提供相关问题有偿答疑和支持。 我们可以使用 static 关键字来把类成员定义为静态的。当我们声明类的成…

华为云鲲鹏架构docker部署2048小游戏

华为云鲲鹏架构docker部署2048小游戏 1. 鲲鹏架构ESC2. 配置docker3. 上传2048镜像4. 删除容器,镜像 1. 鲲鹏架构ESC 2. 配置docker 安装dockeryum -y install docker开机启动 systemctl enable docker启动docker服务 systemctl start docker查询docker的运行版本 docker -v3…

注意力机制之ECA-Net:Efficient Channel Attention for Deep Convolutional Neural Network

论文link&#xff1a;link code&#xff1a;code 1.摘要 近年来&#xff0c;通道注意机制被证明在改善深层卷积神经网络&#xff08;CNN&#xff09;的性能方面提供了巨大的潜力。然而现有的大多数方法都致力于开发更复杂的注意模块以获得更好的性能&#xff0c;这不可避免地增…

1.linux操作系统CPU负载

目录 概述CPU平均负载查看平均负载结束 概述 CPU 使用率 和CPU 平均使用率。 CPU平均负载 单位时间内系统处于 [可运行状态] 和 [不可中断状态] 的平均进程数&#xff0c;就是平均活跃进程数&#xff0c;和CPU使用率并没有直接关系 可运行状态 正在使用CPU或者正等待CPU的进…