当前位置: 首页 > news >正文

Y3编辑器教程5:触发器进阶使用(镜头、UI、表格、函数库、排行榜、游戏不同步)

文章目录

    • 一、游戏声音设计
    • 二、 游戏镜头设计
      • 2.1 镜头的基本参数
      • 2.2 镜头时间轴动画
    • 三、界面编辑
      • 3.1 界面编辑器设置
      • 3.2 添加按钮事件
      • 3.3 触发编写
    • 四、 表格编辑器(实现对话UI)
      • 4.1 一维表和多维表
      • 4.2 数据验证、搜索、保存与撤销
      • 4.3 Excel导入导出
      • 4.4 使用表格编辑器实现对话UI
      • 4.5 更多示例
    • 五、 函数库
      • 5.1 简介
    • 六、项目:竞技场争霸赛
      • 6.1 项目简介
      • 6.2 地形设置
      • 6.3 游戏初始化
      • 6.4 战斗准备
      • 6.5 战斗中
        • 6.5.1 右键移动
        • 6.5.2 左键攻击
        • 6.5.3 Boss AI
      • 6.6 游戏结束
    • 七、 使用排行榜
    • 八、 不同步问题
      • 8.1 本地配置不同步日志环境
      • 8.2 线上游戏不同步定位
      • 8.3 定位不同步问题
      • 8.4 游戏不同步常见原因

  • Y3编辑器文档1:编辑器简介及菜单栏详解(文件、编辑、窗口、细节、调试)
  • Y3编辑器文档2:场景编辑(地形编辑、物件放置)
  • Y3编辑器文档3:物体编辑器
  • Y3编辑器文档4:触发器1(界面及使用简介、变量作用域、入门案例)
  • Y3编辑器教程5:触发器进阶使用(镜头、UI、表格、函数库、排行榜、游戏不同步)

本文参考官方文档《触发器案例》和《触发器初级教程》

一、游戏声音设计

  声音不仅是玩家接收游戏信息的重要途径,也是游戏开发者传递情感和增强游戏体验的关键工具。游戏中的声音主要分为功能性音乐和背景音乐两大类:

  • 功能性音乐:
    • 游戏信息提示:为玩家提供画面外的游戏信息提示和预警,例如交互物品的存在、环境变化和潜在威胁。
    • 玩家操作反馈:通过声音反馈玩家操作,增强游戏互动性,使玩家获得及时且全面的反馈。
  • 背景音乐:
    • 环境渲染:通过声音对游戏场景进行多感官渲染,增强玩家的沉浸感。
    • 情绪渲染:利用声音表达复杂的情绪,如战斗的激烈、对未知的恐惧和紧迫感。

在物体编辑器中可以进入音效模块,设置音效属性:

  • 淡入:设置声音开始时由无声过渡到有声所经历的时间。
  • 淡出:设置声音结束时由有声过渡到无声所经历的时间。
  • 调整至3D声音模式,我们可以设置声音的衰减距离和静音距离。
    在这里插入图片描述
      点击“+”可以为一个音乐场景添加多个声音,不仅可以调节各个声音的音量,还可以调整各个声音的播放概率,从而使游戏中的音乐变得多样化。还可以为音效添加新的自定义属性并设置其名称、类型、值,后续通过触发器调用。
    在这里插入图片描述
      在物编器-单位-单位固定属性中,我们可以为单位绑定声音事件,比如选择当角色升级时播放升级音效。

二、 游戏镜头设计

2.1 镜头的基本参数

  打开工具栏->放置物件->镜头,可以看到编辑器自带得默认镜头Initial Camera,此镜头的视角为进入游戏之后的默认视角,无法删除,无法重命名。用户可以在场景中的任意位置,点击“以当前视角设置镜头属性”来为当前视角创建镜头。用户创建的镜头可以重命名、删除。
在这里插入图片描述

参数说明
焦点位置及镜头的指向点焦点位置指的是镜头所注视的目标点,它由三维坐标(X、Y、Z)确定。镜头的指向是通过这些坐标来设定的,表示镜头当前所看的位置。
俯仰角镜头与水平线的夹角,平视为零度,仰视为负数,俯视为正数。
导航角镜头在地平面上的方向,通常从参考方向(如正北)开始测量,镜头面向正东时导航角为90度。
滚转角镜头自身的旋转角度,类似于歪头时视角的变化。
距离镜头与焦点之间的三维空间距离。
观察区域(FOV)镜头视野所能覆盖的范围,决定镜头显示细节的区域。
远景裁剪镜头显示参数,超出距离范围的物体不进行渲染(不显示)。
实时观察镜头属性改变勾选后可实时预览镜头的视角变化。
与焦点的最大/最小距离游戏中,玩家可通过鼠标滚轮控制镜头与焦点的距离,设置此参数可进行限制。
例如,当二者设为一样时,玩家视角将被限定,无法使用鼠标滚轮调整距离。

在这里插入图片描述

2.2 镜头时间轴动画

  使用镜头时间轴动画和使用触发器都可以实现镜头动画,二者在最终的画面表现上没有区别,但却各有优势:

  • 镜头时间轴动画:可以在时间轴内,通过设置关键帧的形式,方便快速地制作镜头动画。但每条时间轴镜头动画不能复制,无法复用。
  • 触发器:触发器编写的自定义程度高,语句还可以复制粘贴,具有很强的复用性和扩展性。(相关定义详见触发器-镜头API)
    在这里插入图片描述

  点击新建的“镜头时间轴动画1”右侧的编辑按钮,即使用当前画面视角为初始帧,创建时间轴动画。每条时间轴动画由两个部分组成,分别是 时间轴当前关键帧下镜头的属性面板。

在这里插入图片描述

  我们可以在时间轴上拖动进度条,或是在frame窗口中输入具体帧数,来选择关键帧位置。Y3编辑器使用的刷新率为30帧每秒,所以如果设置关键帧在第60帧,就是在第两秒。点击上方的创建按钮,即可在所处位置为所选参数新建关键帧。

  关键帧分为绝对值(当前关键帧下镜头的具体参数)和相对值(相对于初始帧所改变的取值)。当指针选定一个关键帧时,点击鼠标右键,即可对关键帧进行复制、粘贴、删除(按下delete按键也行)等操作。编辑并保存关键帧之后,在触发器中可以编写镜头触发事件:

在这里插入图片描述

三、界面编辑

本节课,我们要实现以下效果:

在这里插入图片描述

  界面编辑器是对软件的人机交互操作逻辑和界面美观进行的整体编辑,我们通常会用到图像、文字、按钮等组件,在界面上与操作者进行互动,从而丰富和增强用户的体验。Y3编辑器中UI编辑器的操作界面主要由五个部分组成:

在这里插入图片描述

  1. 画板区:在开始做一个界面之前,必须先创建一个画板。
  2. 节点区:用于展示每个画板里面的各个控件。所有组件都以树结构来陈列,包含了一组节点,节点之间相互关联,并且具有父节点和子节点关系(节点的任何附属节点都称为子节点)。删除一个节点,其所有子节点也会被一起删除。
  3. 控件栏:展示所有可使用的UI组件,包括按钮、图片、模型、文本输入框、进度条、滑动条列表等。
  4. 画布区:在画布中编辑摆放组件,并查看组件属性。
  5. 属性/事件区:前者用于编辑组件的具体参数,包括大小、位置、外观、动画等;后者配合触发编辑器,去实现一些想要的功能。

3.1 界面编辑器设置

  首先在地图上放置一个用于选择的单——探险者,在法师周围绘制一个圆形区域,命名为select _area,,表示进入这个区域会触发宝物选择界面。

  • 创建空白画布:打开界面编辑器,单击+创建一个新的画板,并重命名为select_treasure。缩放画布大小为33%
  • 创建选择框底板:拖动顶部图片按钮到画布中央,在资源库中选择喜欢的图片(控件->背景纹理->场景立绘装饰框)。拖动图片锚点放大图片,或者通过x轴y轴坐标进行放大。最终坐标(960,540),尺寸(1800,1000)。
  • 设置界面标题:拖动顶部文本按钮到底板上,调整位置和大小,输入“请选择一个你喜欢的宝物”作为选择框的标题,并命名为title。设置文本的字体颜色和对齐方式,让它们看上去更美观一些。

在这里插入图片描述

  • 设置玩家选项1:拖动一张图片(控件图标->蓝色控件图标)到画布上,根据喜好调整位置(700,540)、尺寸(320,400),命名为button1。将另外一个图片(图标->勋章->蓝色面具成就图标)拖动至button1内,作为奖励的展示图标(icon1,尺寸156×156),选择文本并将其拖至button1内,作为奖励的名字(name),输入“魔法戒指”并调整字体颜色和位置。
  • 调整父子级关系:以图片为父节点,将title,button1拖动到图片下,作为相互平行的子节点。将icon,name拖动到button1下,作为其子节点。这样icon,name,button1就可以作为一个整体被选择。
  • 设置玩家选项2:复制并粘贴一个新的选项,重命名为button2,调整级别和位置,更改图像和文本,完成第二个按钮。

在这里插入图片描述

3.2 添加按钮事件

  界面组件设置完毕后,我们为按钮添加事件。选中button1,右上角点击事件,点击+添加事件,并命名为choose_ring。点击“空事件->事件设置-点击”。同样的方式为button2选择点击事件并命名为choose cloak

  在事件板块,点击音效可以选择事件的音效,点击界面上方的动画编辑,可通过时间轴管理为事件制作帧动画。时间轴和动作设置板块中的动画效果互相排斥,如果在动作设置板块中选择了一个动画效果,则时间轴不生效。

在这里插入图片描述
  由于整个画板在事件触发前是不可见的,所以选中整个画板select_treasure,选择属性,将是否可见取消勾选,这样我们绘制的整个界面组件,在触发调用前是不可见的。

3.3 触发编写

整个触发分三部分:

  • 当选择单位进入到对应的区域后,会出现选择框
  • 选择按钮A,左侧信息栏提示A内容
  • 选择按钮B,左侧信息栏提示B内容

下面是具体的编写逻辑:

  1. 触发器-进入区域
    • 在物编器的触发器页签下创建任意单位进入select _area区域事件,将此事件命名为“进入区域”。
    • 新建条件->单位类型判断,获取事件中单位的单位类型等于探险者。
    • 新建动作->界面->显示/隐藏控件,对玩家1显示控件。

在这里插入图片描述

  1. 触发器-选择戒指
    • 创建事件:界面->控件事件,参数UI事件选择choose ring
    • 创建动作选择界面->显示/隐藏控件来向玩家1显示控件select_treasure(选择完毕,不需要再展示选择界面)。
    • 创建动作选择界面->系统消息提示,来向玩家提示“你选择了魔法戒指”,持续时间设为5秒。
  2. 触发器-选择斗篷
    直接复制上一条触发器重命名为选择斗篷,UI事件改为choose cloak,第二条动作命令信息显示内容修改为“你选择了魔法斗篷”。

在这里插入图片描述

应该添加一个全局变量表示经过了选择,即只能选择一次。

四、 表格编辑器(实现对话UI)

在这里插入图片描述
  在故事中,我们通过对话UI向玩家传达了剧情的重要信息。不同的对话内容需要多个UI来呈现吗?其实不用,在Y3编辑器中,我们可以结合表格编辑器、界面编辑器和触发来实现这个效果。

4.1 一维表和多维表

  表格编辑器是Y3编辑器提供的数据管理工具,我们可以在表格编辑器中以表格的形式保存数据,并之后通过触发来快速调用这些数据,比如怪物的物品掉率,刷怪时怪物种类和数量。

  在表格编辑器中有两种表格:一维表和多维表。一维表中,每一行都是一条独立的数据,包含键名、类型、值和备注。通过键名,也就是索引,我们就能快速获取到对应的值。

  一维表适合定义零散的各种数据,比如游戏初始化时的一些规则和参数。假设你的《练功房》项目中一共会有六个房间,你想分配其中有两个房间产出经验,有两个房间产出金币,并且希望在游戏中时间12时开始刷新怪物,14时之后就停止刷新怪物。由于这些数值关系到项目中设定的经济产出,如果你希望快速地调整这些数值,可以将这些数值保存在一维表格中:

在这里插入图片描述

  假设你正在制作一个《塔防》项目,在第1波次,一共有30只恶魔进攻玩家,玩家需要在60秒内把他们消灭。这里波次有“顺序”、“怪物数量”、“怪物类型”、”消灭时间”四个关键属性,可以使用多维表格管理数据。多维表中,每条数据包含多个属性及其数值,我们需要两个索引才能锁定数据位置。

在这里插入图片描述

  多维表适合定义一个数据对象,表格中的第一行是这个数据对象的属性名称(key),第二行是这个属性的数据类型,第三行及之后的行则是对应的值。如果数据类型选错了,那么你可能没有办法在触发器中正确的拿到你想要的数据。

4.2 数据验证、搜索、保存与撤销

  • 多维表可灵活添加行和列,一维表固定只有三列,不能新增列。
  • 不允许出现相同的主索引值,且主索引只能是整型或字符串类型
  • 数据验证:标红的单元格意味着该数据无法在局内读取到。若是在你配置过程中出现,可能只是因为你的表格还没有编辑完成而系统提前在验证。数据配置后,仍有单元格标红,可把鼠标悬浮在红框上查看具体原因,如关键数据的缺失或不匹配或重复,再予以修复。
    在这里插入图片描述
  • 重命名:右键点击一张表或选中后按F2可进行重命名
  • 表格归类:点击文件夹图标按钮或Ctrl+G可创建文件夹,归类表格。
  • 保存与撤销:保存按钮是保存整个工程,而撤销按钮只针对你在表格编辑器内的操作。

4.3 Excel导入导出

  表格编辑器并不支持如office中公式、填充柄、甚至VBA等一些高级功能的应用。如果要进行高效开发,推荐先使用Excel进行快速编辑,再导入编辑器。表格编辑器用于快速验证调试游戏体验。

  点击导入,你可以选择一个表格文件将其导入至编辑器中,当前支持的表格格式有”.xlsx”,”.xlsm”,”.xls”,”.csv”共四种。

  1. 一维表导入:所有以“kv_”开头的sheet将读取为一维表
    • 标题行:第一行为标题行,限定内容为“Key,Type,Value,Des",大小写允许模糊。
    • 数据行:第二行往后为数据行
  2. 多维表导入:所有"config_"作为前缀的sheet表格将读取为多维表
    • 第一行为注释行,不读取
    • 第二行为数据名,读取后视为列名
    • 第三行为数据格式,支持int,string,float,bool四个类型,支持大小写模糊
    • 第四行为主键标识,格式需要是整型或者字符串类型,以key1,key2,key3进行枚举,支持大小写模糊。最多支持三键表,需有key1,才能有key2,需有key2,才能有key3,否则报错,导入错误。如果没有key,则生成一个”key1“列作为主键,以行号填写值。
    • 第五行之后为表格的数据,涉及到的公式等特殊格式以结果的值进行读取。

4.4 使用表格编辑器实现对话UI

在表格编辑器内定义的表格,在游戏初始化时将会保存在内存中,供你在任意的触发器中调用:

在这里插入图片描述
下面我们就来看一看表格编辑器的具体使用方法。

  1. 绘制UI:绘制一个界面来承载和展示对话内容

    • 打开界面编辑器添加一个新面板,并将其重命名为dialogue。这个界面应包含两个图片,一个作为content背景(框体->对话框,527×190),一个作为real name(角色)的背景,以及两个分别用于承载real namecontent文本框。
    • 拖动调整这些控件的大小和位置,在文本设置中设置文本的字体样式(微软雅黑,24),调整空间的父子级关系。选择整个面板并取消勾选是否可见,表示直到它被触发才显示对话界面。
      在这里插入图片描述
  2. 创建多维表:创建多维表并将其重命名为scripts。在scripts中将主索引key修改为order(存储对话顺序,整型)。添加两个类型为字符串的属性role namecontent分别存储角色名称和对话内容。
    在这里插入图片描述

  3. 触发编写

    • 新建事件:硬件输入-键盘空格键按下事件
    • 新建动作设置对话顺序:设置一个全局整数变量order,来记录空格键被按下的次数,初始值为零。使用函数->整数间运算,设置变量orderorder+1,这样当我们第一次按下空格键时,order都加1
    • 新建动作显示角色名称:选择界面->设置文本,对玩家一设置dialogue面板下的real name文本,字符串参数选择函数,然后选择第二个多维表中的字符串值。现在当我们第一次按下空格键时,order=1,主索引为1role name数据将读取显示。当我们再次按下空格键时,order=2,主索引为2role name的数据将被读取显示。
    • 新建动作显示角色对话文本:操作同上

在这里插入图片描述

4.5 更多示例

一维表用例:配置了如下的一维表,命名为globalConfig
在这里插入图片描述
可直接通过Type类型对应的参数类型,在获取到Key对应的Value值。

在这里插入图片描述
多维表用例:配置了如下的多维表,命名为Example。
在这里插入图片描述
最基础的使用方式为直接获取表格中的值,如我当前需要获得id为1的数据中的use_money字段数据,将其存入变量a中。可以采用这样的方式:
在这里插入图片描述
常用方式是遍历表格,实现一些逻辑:

在这里插入图片描述

五、 函数库

5.1 简介

在这里插入图片描述
  在之前的章节中,我们使用循环计时器连续生成次元入侵者。那如果需要在多个区域,在不同的时间点生成敌人,是否需要写多个触发器重复设置效果呢?当然不是,Y3编辑器为我们提供了一种更简单的方法来重复实现简单的功能,即函数库。

  你可以将自己常用的触发器语句/功能模块添加到函数库,接着就可以在触发器中找到该函数语句进行重用。与触发器的操作逻辑相同,在左侧创建函数后,在右侧编辑功能库函数。

在这里插入图片描述

初始化玩家技能槽位

函数描述定义了函数在操作列表中的显示方式。 函数描述包括以下内容:

  • 名称:要生成的触发器语句的名称。
  • 描述:要生成的触发器语句的内容和格式。
  • 提示:当前函数的说明。

在这里插入图片描述

函数体包括以下内容:

  • 参数:定义了该函数的输入数据,可设置参数类型,如定时器、单位和整数。
  • 返回值:定义了函数执行后返回的结果(输出数据)。你可以点击 "+"来设置返回值的名称和类型,以方便触发器的后续调用。
  • 动作:显示了函数的具体行动逻辑

  现在我们想要实现的效果是,在三个指定的地点间隔0.3秒,生成一个指定类型的野怪,总共生成五个。我们可以使用函数库简化具体的编写过程。
在这里插入图片描述

  1. 触发组件:我们需要在地形上放置敌对单位、boss和探险者。
    • 在boss周围绘制三个点区域,分别命名为point A、Point B、Point C。
    • 以boss为中心绘制一个圆形区域alert area,作为boss的警戒范围
    • 自定义三个不同的小怪,他们会在三个点生成。
  2. 自定义函数库函数
    • 在函数库中新建函数,命名为“野怪刷新”,参数为Monster(小怪,单位类型)和Point(刷新点)
    • 点击左边的可用参数,使用刚刚创建的参数组成函数描述:“在参数Point处创建参数Monster”
    • 新建一个技数计时器,设定每隔0.3秒运行一次,共运行五次,选择“立即执行”
    • 在动作列表中选择创建单位,单位类型是参数Monster,点是函数参数Point,为单位boss创建,方向是单位boss的方向。
    • 添加一个动作来向怪物发出命令,选择“单位发布命令”,设置命令为“攻击移动”。
      在这里插入图片描述
  3. 触发编写:调用函数库,通过设置不同的参数和计时器来在不同时间和地点生成敌人。
    • 新建“任意单位进入区域事件”
    • 在单玩家位进入BOSO警戒区域两秒、三秒、四秒后,分别使用“野怪刷新”函数,在三个点刷新小怪。
      在这里插入图片描述

六、项目:竞技场争霸赛

6.1 项目简介

在这里插入图片描述

游戏的制作一般分为三大类:

  • 设计:包括游戏的核心玩法和故事背景。
  • 美术:负责游戏的原画,角色、物体和场景的三维建模。
  • 程序设计:通过代码实现游戏玩法。

  本项目“竞技场争霸赛”是一款射击类小游戏,一个人就足以完成开发。核心玩法是玩家控制挑战者挑战怪物,通过移动和射击来躲避怪物攻击和击败怪物。每隔几秒钟怪物就会热身蓄力,然后冲锋,玩家必须使用鼠标右键移动进行躲避,然后使用鼠标左键精瞄准射击,击败怪物,所以游戏两大核心机制是移到和射击
在这里插入图片描述

  另外游戏将从游戏印象和游戏沉浸两个角度进行设计。由于挑战者在攻击时不能移动,所以玩家在何时躲避危险和何时瞄准目标之间保持平衡是很重要的,这带来了挑战和乐趣。在游戏沉浸方面,我们可以通过动画、镜头、角度、滤镜等去创造过程,带来令人印象深刻的游戏体验,玩家将在游戏开始时更加兴奋,在游戏结束时更感到印象深刻。

在这里插入图片描述
在这里插入图片描述

时间有限,下面只展示必要步骤。

6.2 地形设置

  • 新建空白工程,选择小型地图(64×64)和自定义UI模板。
  • 创建生物单位(挑战者、boss、观众)和抛射物(探险者的子弹)。
    • 挑战者模型选择仙人掌人,血条样式为绿色血条,显示模式为不满血显示,取消勾选死亡后销毁单位,取消勾选无法反击时逃跑。最大血量设为30,生命恢复设为0。
      在这里插入图片描述

    • 复制挑战者模板,BOSS模型选择图示小怪物,血条显示红色,单位状态里设置禁止普攻,

    • 观众选择图示小怪物,无血条显示,单位状态选择无效

    • 抛射物选择绿色法阵符文特效,缩放0.6
      在这里插入图片描述

  • 绘制陆地碰撞
    在这里插入图片描述
    在这里插入图片描述
  • 为挑战者、BOSS和观众设置出生点
  • 设置挑战者和BOSS的战斗准备圈
  • 放置一个几乎覆盖整个竞技场的战斗圈,作为boss的攻击区域
    在这里插入图片描述

6.3 游戏初始化

在“竞技场争霸赛”这款游戏中,我们将游戏分为以下四个阶段:

  • 游戏初始化:镜头跟随玩家,设置变量为游戏角色伤害初始值。
  • 战斗准备:挑战者和boss的嘲讽动作,摄像机跟随。
  • 战斗中:实现鼠标操作(右键移动、左键射击),boss的AI逻辑(蓄力和冲锋)。
  • 战斗结束:根据胜者播放不同的动画和滤镜效果,结束游戏。

我们先完成第一阶段:游戏初始化

  • 刷出挑战者,并设置镜头,让玩家以第三人称视角跟随他。
  • 设置一个2s的计时器,给玩家一点缓冲时间,让他们意识到游戏即将开始。
  • 向挑战者发布命令,移动到挑战者准备区
  • 为了提高游戏的沉浸感,邀请观众参加战斗。
    • 点击基础->收纳盒,设置一个存储框,设置一个观众点数组存储所有观众点,设置完后折叠起来,使界面更简洁。
      在这里插入图片描述

    • 设置一个循环来生成观众,并让他们的方向朝着战场中心。最后将每个观众都添加到观众单位组中,这样游戏结束时,我们就可轻易命令单位组成员,播放庆祝或挫折动画了。
      在这里插入图片描述

6.4 战斗准备

当挑战者进入准备圈时,我们需要做三件事:

  • 移除挑战者的准备圈,防止重复挑战者准备逻辑
  • 挑战者停止下来,播放嘲讽动画作为准备战斗的信号
  • boss进入战斗区域,并使用镜头跟随它
    在这里插入图片描述

当BOSS进入它的准备圈时,也有三个工作:

  • 移除boss的准备圈
  • 播放boss嘲讽动画将比赛气氛推向高潮
  • 等待2s后战斗开始,让镜头恢复正常,并允许玩家控制角色。

最后创建一个全局布尔变量battleongoing,默认值为false,现在为true,表示正在战斗中。

在这里插入图片描述

6.5 战斗中

6.5.1 右键移动

  为了在游戏中实现鼠标操作,我们设置了右键移动,左键射击。移动机制为,当玩家按下鼠标右键,并且布尔变量battleongoing为真时,让角色移动到鼠标位置。

在这里插入图片描述

6.5.2 左键攻击
  • 当玩家按下鼠标左键且battleongoing为真时,创建一个局部变量为鼠标的游戏坐标,point为当前玩家坐标
  • 命令挑战者停止(防止可以边移动边攻击),将方向设置为从point朝向clickedPoint的方向,播放攻击动画
  • 完成开枪逻辑:
    • point处创建投射物(设为变量方便移除),添加运动器来设置子弹的直线运动轨迹和造成的伤害
    • 在移动完成后将运动器和抛射物移除
    • 创建碰撞运动器实现子弹的射击伤害,并跳字显示

在这里插入图片描述

6.5.3 Boss AI

Boss的AI逻辑有两个部分:蓄力和冲锋。

  • 每三秒,如果battleongoing为真,怪物将停止移动并播放循环蓄力动画idle2
  • 2秒钟后怪物会播放一个循环冲锋动画,并为自己创造一个线性的移动器,达到高速移动的效果。BOSS移动位置为战斗区中随机位置。
  • 使用碰撞移动器让BOSS冲锋时对碰撞的敌方单位造成真实伤害

在这里插入图片描述

6.6 游戏结束

当任何单位死亡时,战斗结束。我们需要停止玩家的控制权限,播放结束过场动画,并结束游戏。

  • 创建一个触发器,触发事件为任意单位死亡
  • 设置battleongoing为False
  • 将摄像机对准胜者,如果是挑战者,这意味着玩家赢了,让我们为挑战者和所有观众播放赢家动画。设置一个闪闪发光的滤镜效果,使这个庆祝时刻更愉快,并以胜利结束游戏。
  • 如果胜者是boss,播放输家动画,设置对应的滤镜。

在这里插入图片描述

七、 使用排行榜

  1. 点击主界面【细节】-【存档设置】打开存档槽设置

  2. 点击加号创建一个新的存档槽并修改存档槽数据类型为整数
    在这里插入图片描述

  3. 选择确认计入排行榜,这个存档槽位就变成了排行榜存档。可以选择排行榜排序规则(升序降序)与排行榜最大人数。
    在这里插入图片描述

  4. 使用以下eca可以获取排行榜上所有玩家的存档值,配合界面eca让排行榜在界面显示。玩家->整数型增量存档eca可以让整数类型存档保持只增效果。
    在这里插入图片描述

排行榜数据在游戏启动后不会再刷新,使用双槽位可以实现周排行榜

  • 创建两个整数类型存档槽位:A与B,A存储第一周所有玩家的排行榜数据

  • 当一周结束时(通过时间戳判断),使用B榜存储玩家在第二周的排行数据

  • 在第二周开始时通过ECA清除玩家A槽位数据,以备第三周存储玩家排行数据。需通过在作者之家清除A榜数据(权限需找运营申请)。
    在这里插入图片描述

  • 当第二周结束时,将玩家排行榜数据存储在A榜并清除B槽位数据,循环往复

八、 不同步问题

参考《不同步相关》

8.1 本地配置不同步日志环境

  用户由于使用ECA不当,频繁出现游戏逻辑不同步的问题,会影响游戏正常运行。此时可通过在本地多开测试来进行调试。在【通用设置-调试】打开本地多开同步检测。

在这里插入图片描述
  使用Lua文件配置更详细的不同步日志:打开地图路径下Script文件夹下的main.lua文件,在lua文件中配置不同步日志相关API
在这里插入图片描述

GameAPI.api_set_enable_detail_snapshot(true)
GameAPI.api_set_detail_snapshot_enable_tag(0xfffffff)
GameAPI.api_set_enable_eca_snapshot(true)
GameAPI.api_set_snapshot_traceback_level(2)

  配置完毕后,本地多开运行游戏。如遇游戏逻辑不同步,会有弹窗提示,并在本地生成不同步日志以供用户定位不同步问题。
在这里插入图片描述
在这里插入图片描述

不同步日志Lua配置API说明:

API描述参数返回值
api_set_enable_detail_snapshot控制不同步日志记录的总开关。关闭后,其他设置接口将不生效,但可以提升性能。enable(bool):是否开启,默认为false
api_set_snapshot_traceback_level设置日志堆栈记录详细等级,默认0不记录
1:仅记录最近一层堆栈
2:记录完整堆栈(数据压缩)
3:记录完整日志(不压缩,数据量稍大)
记录越完整越有利于定位问题,但开销增大
level(int32):堆栈记录等级,默认值为0
api_set_enable_timer_snapshot开启或关闭计时器不同步检测日志(检测额外创建的ECA计时器),但计时器不一致并不一定意味着游戏内容不同步。enable(bool):默认值为false
api_set_enable_eca_snapshot开启或关闭ECA不同步检测日志,开销较高。可通过参数过滤掉一些安全的API以防止误报,例如创建特效、UI操作等enable(bool):默认值为false
filter_mode(int32):过滤模式,默认为1
1:剔除模式,不记录filter_set中指定的api;
0:包含模式,仅记录filter_set中指定的api;
filter_set(table):过滤集合,默认为"client_only","client_possible"
可传入想要剔除/包含的API(取决于上个参数)
如"GameAPI:print_to_dialog",“GameAPI:get_function_return_value。”
api_set_detail_snapshot_enable_tag设置不同步详细日志级别。越详细越利于定位不同步产生点,但性能消耗会增高tag(UInt64):控制开启哪些日志的mask
1运动器tick;2运动器碰撞检测
4寻路回调;8寻路坐标更新
16血量变化;32坐标瞬变
0xFFFFFFFF全部开启;默认开启16+32
add_detail_log记录自定义日志log(string):日志内容bool,值恒定为true

8.2 线上游戏不同步定位

  1. 在本地配置不同步日志环境
    打开地图路径下Script文件夹下的main.lua文件,在lua文件中配置不同步日志相关API,这样线上游戏发生不同步时,根据配置API玩家客户端会自动上传日志。例如:
GameAPI.api_set_enable_detail_snapshot(true)
GameAPI.api_set_detail_snapshot_enable_tag(0xfffffff)
GameAPI.api_set_enable_eca_snapshot(true)
GameAPI.api_set_snapshot_traceback_level(2)
  1. 下载不同步日志
    使用KK账号登录编辑器,打开任意地图,点击【菜单栏】【调试】【查看不同步日志】查看线上游戏的不同步日志。
    在这里插入图片描述
    查找需要定位问题的对局,下载不同步日志,不同步日志包含对局中所有玩家的对战信息。
    在这里插入图片描述

8.3 定位不同步问题

  不同步日志文件中包含的是出现不同步情况的帧信息,通过对比玩家日志差异,可以大致定位到问题所在。打开不同步日志文件夹,使用第三方文本对比工具进行对比(推荐使用BeyondCompare)。比如在main.lua文件中进行了如下配置:

GameAPI.api_set_enable_detail_snapshot(true);
GameAPI.api_set_enable_timer_snapshot(true);

打开不同步日志,查看逐帧信息:

在这里插入图片描述
将多名玩家日志成对拖放到beyondcompare中进行对比,发现玩家2比玩家1多了一个timer:
在这里插入图片描述
  通过对不同步信息附近的帧信息进行理解,可大致定位问题为某个客户端上多了一个循环计时器,在项目中进行查找可能的问题所在。
在这里插入图片描述

8.4 游戏不同步常见原因

  • 本地值
    • 在单个客户端(即单个玩家的设备)上有效的数据,比如界面显示、特效、镜头位置、声音等,这些数据在不同的客户端之间不需要同步,因为它们只影响单个玩家的体验。
    • 任意值与【本地值】进行逻辑运算后得到的值等价于【本地值】
    • 动作类ECA中,修改【本地值】,不会影响游戏的全局逻辑,因此不会影响游戏的同步性。
  • 本地操作:针对本地值的操作,如【获取本地玩家】、【获取本地控件坐标】、【获取镜头焦点】、【获取滑动条当前值】等,这些获取本地值的ECA函数,在不同客户端得到的结果也是不同的。
  • 全局值:在所有客户端之间需要保持一致的值,比如单位、技能、物品等。这些值的一致性对于游戏的公平性和逻辑一致性至关重要。
  • 全局操作:针对全局值的操作,比如修改单位的状态、技能的效果、物品的数量等。这些操作会影响游戏的全局逻辑,因此需要确保在所有客户端上都能正确同步。

  导致游戏逻辑不同步的一个重要原因就是将【本地值】作为参数,传递到【全局操作】中,或者是使用【本地值】进行逻辑判断后,进行【全局操作】。这会导致不同客户端执行不同的逻辑,最终导致不同客户端上【全局值】不同,即游戏逻辑不同步。更多内容详见文档多人联机同步机制。

相关文章:

Y3编辑器教程5:触发器进阶使用(镜头、UI、表格、函数库、排行榜、游戏不同步)

文章目录 一、游戏声音设计二、 游戏镜头设计2.1 镜头的基本参数2.2 镜头时间轴动画 三、界面编辑3.1 界面编辑器设置3.2 添加按钮事件3.3 触发编写 四、 表格编辑器(实现对话UI)4.1 一维表和多维表4.2 数据验证、搜索、保存与撤销4.3 Excel导入导出4.4 …...

基于小程序实现地图定位、轨迹绘制、地图标点、快捷导航、唤醒导航APP、开箱即用

目录 前言研究背景与意义研究目标与内容研究方法与技术路线小程序地图组件介绍定位技术与原理轨迹绘制技术地图标注与标记功能地图定位与轨迹绘制功能实现定位功能设计与实现获取用户当前位置总结说明代码块前言 研究背景与意义 地图定位和轨迹追踪作为智能手机中常见的功能之…...

JAVA后端实现全国区县下拉选择--树形结构

设计图如图&#xff1a; 直接上代码 数据库中的格式&#xff1a; JAVA实体类&#xff1a; Data public class SysAreaZoningDO {private Long districtId;private Long parentId;private String districtName;private List<SysAreaZoningDO> children; } MapperSQL语句…...

数据结构速成

1. 数据结构与算法 2. 顺序表 3. 链表 4. 栈与队列 5. 串 6. 树与二叉树&#xff08;1&#xff09; 7. 树与二叉树&#xff08;2&#xff09; 8. 图 9. 图的应用 10. 查找 11. 排序&#xff08;1&#xff09; 12. 排序&#xff08;2&#xff09;...

Electron-Vite 项目搭建(Vue)

前提条件 Node.js: 确保已安装 Node.js 版本 18 或更高版本 (推荐使用最新稳定版)。Vite: 确保 Vite 版本为 4.0 或以上。包管理工具: 推荐使用 pnpm&#xff0c;但也可以使用 npm 或 yarn。 安装 Electron-Vite 首先&#xff0c;在项目中安装 electron-vite 作为开发依赖&a…...

如何寻找和改进开源项目来作为个人简历项目

寻找开源项目&#xff1a; 使用开源代码平台&#xff08;如GitHub&#xff09;来搜索优质的开源项目。例如&#xff0c;可以通过搜索关键词如“spring boot”&#xff0c; in name spring boot或者使用更具体的条件&#xff0c;如“star大于1000”来筛选热门项目。 star:>…...

STEM真题 第五题 比 n 小的最大数

题目描述 给定一个正整数 n&#xff0c;请将 n 中的每位数字重新排列并组成一个新数&#xff0c;要求新数的值要小于 n&#xff0c;请找出所有 符合要求的新数中最大的那个正整数&#xff0c;如果不存在这样的正整数&#xff0c;则输出 -1。例 1&#xff1a;n 312&#xff0…...

HuggingGPT Solving AI Tasks with ChatGPT and its Friends in Hugging Face 论文解读

1. 引言 近年来&#xff0c;大型语言模型&#xff08;LLMs&#xff09;如ChatGPT在自然语言处理领域取得了惊人的进展&#xff0c;展现出强大的语言理解、生成和推理能力。然而&#xff0c;当前的LLMs仍然存在一些局限性&#xff0c;例如无法处理复杂信息&#xff08;如视觉和…...

深入了解HTTPDNS-使用Python实现一个HTTPDNS服务

深入了解HTTPDNS-使用Python实现一个HTTPDNS服务 HTTPDNS的起源 传统的DNS&#xff08;Domain Name System&#xff09;是互联网的核心协议之一&#xff0c;负责将人类可读的域名解析为机器可理解的IP地址。经典的DNS查询基于UDP协议&#xff0c;在特定网络环境下可能存在如下…...

IDEA 可视化使用 git rebase 合并分支步骤 使git分支树保持整洁

模拟环境 dev 分支开发完一个功能&#xff0c;需要合并到 master 分支&#xff0c;如果现在直接 merge 合并的话 git分支树会出现杂乱分叉&#xff0c;先把 master 分支 rebase 到 dev git分支树就会是整洁的一条直线 git rebase介绍 rebase:翻译成中文是重新设定&#xff0c;…...

网络安全教学博客(二):常见网络安全威胁剖析

在上一篇博客中&#xff0c;我们了解了网络安全的基础概念和重要性。今天&#xff0c;让我们深入探讨一下常见的网络安全威胁&#xff0c;以便我们能够更好地识别和防范它们。 恶意软件&#xff08;Malware&#xff09; 病毒&#xff08;Virus&#xff09;&#xff1a;病毒是一…...

区块链技术及应用(期末考试版)

简述区块链中的默克尔树结构及其作用。 默克尔树&#xff08;Merkle Tree&#xff09;是一种二叉树数据结构&#xff0c;其叶节点是数据块的哈希值&#xff0c;而每个非叶节点是其子节点哈希值的哈希。它的主要作用是高效且安全地验证大规模数据结构中的数据内容。 解释为什么…...

Ubuntu22.04 docker如何发布镜像(和用git差不多)

在dockerhub上创建远程仓库&#xff1a;https://hub.docker.com/ 将本地镜像打tag&#xff0c;并修改成可以上传到 dockerhub 的形式 # 查看本地镜像# 修改镜像 ## docker tag 镜像名称:标签 新的镜像名称&#xff08;要和远程仓库dockerhub上的一致&#xff09;:新的标签pus…...

基于python绘制数据表(上)

利用python绘制各种数据图表 绘制柱形图-源码 from openpyxl import Workbook from openpyxl.chart import BarChart, Reference# 创建工作薄 wb Workbook(write_onlyTrue) # 创建工作表 ws wb.create_sheet(月收入)# 准备数据 rows [(月份, 销售额),(1, 23),(2, 43),(3, …...

【机器学习】在向量的流光中,揽数理星河为衣,以线性代数为钥,轻启机器学习黎明的瑰丽诗章

文章目录 线性代数入门&#xff1a;机器学习零基础小白指南前言一、向量&#xff1a;数据的基本单元1.1 什么是向量&#xff1f;1.1.1 举个例子&#xff1a; 1.2 向量的表示与维度1.2.1 向量的维度1.2.2 向量的表示方法 1.3 向量的基本运算1.3.1 向量加法1.3.2 向量的数乘1.3.3…...

Python PPT合并与拆分 – 详解

目录 使用工具 Python 合并 PPT 合并多个PPT文档 合并每个PPT文档中的特定幻灯片 Python 拆分 PPT 按幻灯片数量拆分 按幻灯片范围拆分 按幻灯片内容拆分 按节 (Section) 拆分 在日常工作或学习中&#xff0c;我们经常需要对PPT文件进行调整&#xff0c;比如将多个PPT…...

舌头分割数据集labelme格式2557张1类别

数据集格式&#xff1a;labelme格式(不包含mask文件&#xff0c;仅仅包含jpg图片和对应的json文件) 图片数量(jpg文件个数)&#xff1a;2557 标注数量(json文件个数)&#xff1a;2557 标注类别数&#xff1a;1 标注类别名称:["tongue"] 每个类别标注的框数&#xff1…...

LVS能否实现两台服务器的负载均衡

LVS能否实现两台服务器的负载均衡 是的&#xff0c;LVS&#xff08;Linux Virtual Server&#xff09;可以实现两台服务器的负载均衡&#xff0c;并且它非常适合这种场景。 LVS&#xff08;Linux Virtual Server&#xff09;简介&#xff1a; LVS 是一种基于 Linux 的负载均…...

onlyoffice 容器配置修改后制作镜像导出以及上传到 dockerhub

1.将容器制作成新的镜像 docker commit -p -a "xxx" -m "zh-cn-20-100" onlyoffice ooffice:7.1.1.23docker commit: 这是 Docker 中用于创建新镜像的命令。 -p: 这个选项用于在提交之前暂停容器的运行。这可以确保数据的完整性&#xff0c;因为容器在提交…...

Java常用 Date 时间格式化、Calender日历、正则表达式的用法

目录 1. SimpleDateFormat 日期格式化类 1.1 Date 类型转 String 1.2 String 类型转 Date 2. Calendar 日历类 3. 正则表达式 3.1 正则表达式的组成部分 3.2 手机号正则表达式 3.3 常用密码校验正则表达式 1. SimpleDateFormat 日期格式化类 SimpleDateFormat 是Java中…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

P3 QT项目----记事本(3.8)

3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案

随着新能源汽车的快速普及&#xff0c;充电桩作为核心配套设施&#xff0c;其安全性与可靠性备受关注。然而&#xff0c;在高温、高负荷运行环境下&#xff0c;充电桩的散热问题与消防安全隐患日益凸显&#xff0c;成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

Python ROS2【机器人中间件框架】 简介

销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发&#xff0c;后来由Pivotal Software Inc.&#xff08;现为VMware子公司&#xff09;接管。RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用 Erlang 语言编写。广泛应用于各种分布…...

Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换

目录 关键点 技术实现1 技术实现2 摘要&#xff1a; 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式&#xff08;自动驾驶、人工驾驶、远程驾驶、主动安全&#xff09;&#xff0c;并通过实时消息推送更新车…...

【 java 虚拟机知识 第一篇 】

目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

日常一水C

多态 言简意赅&#xff1a;就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过&#xff0c;当子类和父类的函数名相同时&#xff0c;会隐藏父类的同名函数转而调用子类的同名函数&#xff0c;如果要调用父类的同名函数&#xff0c;那么就需要对父类进行引用&#…...

用 Rust 重写 Linux 内核模块实战:迈向安全内核的新篇章

用 Rust 重写 Linux 内核模块实战&#xff1a;迈向安全内核的新篇章 ​​摘要&#xff1a;​​ 操作系统内核的安全性、稳定性至关重要。传统 Linux 内核模块开发长期依赖于 C 语言&#xff0c;受限于 C 语言本身的内存安全和并发安全问题&#xff0c;开发复杂模块极易引入难以…...

大模型——基于Docker+DeepSeek+Dify :搭建企业级本地私有化知识库超详细教程

基于Docker+DeepSeek+Dify :搭建企业级本地私有化知识库超详细教程 下载安装Docker Docker官网:https://www.docker.com/ 自定义Docker安装路径 Docker默认安装在C盘,大小大概2.9G,做这行最忌讳的就是安装软件全装C盘,所以我调整了下安装路径。 新建安装目录:E:\MyS…...