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

2024 抖音欢笑中国年(三):编辑器技巧与实践

前言

本次春节活动中,我们大部分场景使用内部的 SAR Creator互动方案来实现。

SAR Creator 是一款基于 TypeScript 的高性能、轻量化的互动解决方案,目前支持了Web和字节内部跨端框架平台,服务于字节内部的各种互动业务,包括但不限于抖音春节、抖音直播礼物、抖音UG活动等。

c77ecd1f40b0c06260f89cf4784504e4.png

SAR Creator 编辑器支持了图形化界面,提供了各类完善的系统(光照、动画、脚本等)供用户快速便捷的搭建一个高质量的互动场景,集成了场景搭建、资源配置、预览调试等功能,并提供了打包构建等工程化插件,可配合业务定制高效2D、3D内容生产工作流。

本文将就本次春节活动中编辑器的工作流程、开发常用功能、以及配套的工程配置方案等进行介绍。

工作流程

目前编辑器的工作流程能极大的提升开发效率,在于研发和设计能够极好的解耦工作。对于设计同学来说,不仅能在研发同学在线编辑器上协作,也能独立制作通过Asset Package包进行资产的交付;而对于开发来说,编辑器能够可视化的进行大部分场景搭建以及资产配置,能直观的检查资产信息。

906f200aa59bd0fea91368bc9377b237.png

资产制作

由于设计同学本地没有开发环境,为了方便设计同学脱离研发单独使用SAR Creator制作美术资产,我们提供了SAR Creator Launcher工具供美术使用,使用 Sar Creator Launcher 可以管理 Sar Creator 编辑器的多个版本安装创建新项目快速启动项目查看编辑器版本的更新信息等功能。

5bdcf9795be11c1e902ef83dca3350c4.png

设计同学使用Launcher搭建一个项目之后,可以将他从PS、Blender、Spine制作的资源导入到SAR Creator当中进行组合到场景当中,并导出成预制体资源,例如春节活动以下场景就是由设计同学制作然后交付给研发使用。

42c8bedec92635dee467484046d9d986.png

动效预览

设计同学产出的资源可以直接导入到SAR Creator中进行播放预览以及调整,美术可以确保最终交付给研发的动画资源是符合预期的。

beb956a77fcc67b760305144d5b31a23.png

目前支持的动画有 lottie、spine、帧动画、模型动画、组合动画以及帧差动画。

资产导出

设计同学最终的导出产物一般为prefabs资源,因为设计和研发的项目不互通,需要一种更快捷的方式同步资源,设计同学可以在创建的预制体右键导出资源包,此功能会将预制体依赖的所有资源导出为一个asset压缩包,设计同学可以直接将此压缩包发送给研发同学导入

16caf2707223d84e81e608d2ff08b768.png

d146610c67261366b5d1083f75eaf9a8.png

研发同学直接在game目录上右键选择导入资源包,即可选择设计同学交付的文件将资源导入

810e15a6cbcd6cb3f83205499629451f.png

68ed939d7073af76af9e84fba21c0ea5.png

功能介绍

画布适配

画布适配是指调整互动区域的视觉输出以适应不同的屏幕尺寸和分辨率,这样可以确保互动区域在不同分辨率的设备上看起来运行都正常。

57a549f6b30d397d6513061effb77ecc.png

SAR Creator 提供了简单的解决方案,首先需要指定设计的宽度和高度,它们定义了游戏将以何种分辨率进行开发,通过设定这些值可以确保互动区域在所在目标设备上正确缩放并保持一致的视觉呈现。

除此之外除了为了进一步增强画布的适配功能,我们提供了根据特定需求的各种适配策略。这些策略包括:

  • FixedWidth(固定宽度):在此策略中,互动区域保持其设计宽度,高度根据纵横比自动调整。这确保互动区域始终占据屏幕的整个宽度,没有重要信息被裁剪掉。

  • FixedHeight(固定高度):与固定宽度策略类似,互动区域保持其设计高度,而宽度则根据纵横比调整。这可以确保互动区域始终垂直填充屏幕,并在各种设备上提供一致的体验。

  • Auto(自动适应):此策略将互动区域按比例缩放以适应可用屏幕空间的宽度和高度。取决于设备的纵横比,两侧或上下可能会出现一些空白区域,但整个互动区域内容都是可见的且无失真。

2D&3D混合开发

互动场景的编辑中,经常需要2D和3D元素相互结合才能创造出更好的交互体验,3D模型的移动经常能带来更逼真的效果,2D元素经常应用于背景图或者UI元素。

a1f0813a0a41728626e639d7cedc62e7.png

通过使用SAR Creator编辑器,可以很轻松的在同一场景中同时添加2D和3D对象。而且SAR Creator编辑器还允许自由调整这些对象之间的层级关系、渲染顺序以及视觉表现。此外,还可以为场景设置多种灯光和相机效果,进一步丰富场景表现力。

使用2D用来编辑器场景UI,对比使用前端技术编写UI界面逻辑,可视化拖拽编辑能大大提升开发速度,拿之前的一个项目举例:

  • 左下界面UI是使用前端技术方案代码编写界面,耗时3天。

  • 右下UI是使用SAR Creator 2D场景制作,耗时0.5天。

33d910c66f505a8e98a9dba26a4bd1d1.png

302a32eb4a2790c0432b075de532089a.png

Bundle分包

在项目开发过程中,资源管理和加载优化是至关重要的。随着互动内容变得越来越丰富,会出现资源体积庞大、加载速度缓慢等问题。为了解决这些问题,SAR Creator编辑器提供了Bundle分包能力,帮助开发者轻松地对游戏资源进行分组、管理和优化。

1692c2955f530f2565c1d5a24064b968.png

a0a90849f89e1c2da3a37bdf393fba84.png

21e1b28e24e87e265afe96ea0ec6ec41.png

Bundle分包使用起来非常简便,只需要选中文件夹,然后如左上图所示,勾选上配置为Bundle,就可以在构建的时候将这个文件夹内的资源拆分为独立的Bundle包,分组选项中有三种资源合并类型,功能介绍如下

  • 无:不做任何优化;

  • 合并依赖:将Bundle中相互依赖的资源二进制文件合并在一起,从而减少运行时加载请求次数;

  • 全部合并:将Bundle中所有资源二进制文件合并为一个,最大化减少请求数量,但可能会增加单个资源加载时间。

用户可以根据自己bundle包的资源情况合理选择分组方式。使用Bundle分包可以让开发者按需加载分包资源,无需项目初始化时就加载所有资源,这样不仅能减少项目首包的大小,还能提升游戏的启动速度和运行效率。

图片分级

图片资源的大小不仅影响着项目最终的包体大小,分辨率大的图片同样会占用设备更多的内存以及性能,而不同的设备的性能是不一样的,为了达到最好的显示效果又要满足用户设备的性能要求,SAR Creator编辑器对图片提供了分级功能,可以使不同性能的设备加载不同分辨率级别的图片,这在春节活动中得到了广泛使用。

0a7fccb3b4bba98a024d55e0f976b925.png

当勾选去掉禁用分级后,构建的时候会生成normal、medium、low三个级别的文件资源,其中medium、low的图片分辨率会低于原始图片,会根据用户手机的性能评分下发不同等级的图片资源,而无需研发同学关心下发的内容。

f3be30d8d1b6b1c0092012e2b9b08805.png

e3c8be38cd10a08b463efe68bc2ca33e.png

需要注意的是,在使用图片分级时,实际上是会修改图片的分辨率大小,而当我们使用spine或者序列帧这类动画文件时,图片资源为图集,如果降低了图片的分辨率,它们就无法在图集上获取正确的像素数据,导致动画播放异常,因此针对图集文件或者动画文件的图片资源,我们需要禁用分级。

压缩纹理

压缩纹理,是一种 GPU 能直接读取并显示的格式,使得图像无需在 CPU 侧解压成 bitmap 即可直接传入 GPU 进行渲染,节约大量的显存开销,而在移动端即内存开销。

在图片的检查器中,勾选上使用压缩纹理即可开启使用,压缩纹理在运行时会根据运行环境自动判断是否使用压缩纹理,使用时用户无需关注。

f8e8832c32ef505b8eeff49261484f60.png

4c69f4ee3e6b4fc1a9808b0910fa4ff3.png

启动图片上的压缩纹理配置后,可以配置选择etc、astc类型的压缩纹理,并通过排序决定运行时加载的优先级。同时可以配置压缩纹理的压缩质量、是否翻转等属性。

另外需要注意的是

  • 压缩纹理不能翻转纹理,即 flipY 表现始终为 false

  • 压缩纹理不能生成 mipmap,即 generateMipmaps 始终为 false

  • 为了适配不兼容压缩纹理的机型,图片资源仍然会被打进包体当中,所以包体会存在图片和图片的压缩纹理资源,包体体积会变得更大

透明像素扩边

在Canvas中绘制图片纹理时,图片边缘的像素会比较难处理,当我们选择边缘像素插值方式为linear时,虽然边缘会更光滑,但是由于插值方式的原因,图片的像素边缘会有一圈黑边,如下左图所示:

b4605170bc145ebfd8817242ad3a9706.jpeg

7865be46c5ae46a3d3aaedd97218aa2c.jpeg

因此,为了解决这个问题,SAR Creator编辑器提供了透明像素扩边的能力,我们可以通过图片配置勾选上透明像素扩边,将图片的边缘增加一圈纯白像素,使插值的像素可以不为黑色,如果扩边单个像素为白色不明显时,我们也可以选择扩全部像素,将透明像素图片的所有透明像素点填充为通过插值计算的带有颜色透明度的像素点,避免边缘渲染时产生黑边。

b87b8c2c6ebc881fee0937e0ac273048.png

841eeff679e2ede36f59935e836ef493.png

不过透明像素扩边同样存在着一些问题,经过扩边操作的图片因为会修改原先的图片文件,所以会导致图片体积增大,具体的增大情况要看最终的图片产物。

工程配置

配置文件

SAR Creator的配置文件主要分为两块:

  • SAR Creator项目的配置文件,其指定了项目的路径、入口文件等基础信息以及SAR Creator中预览的一些基础配置,方便运行项目的时候找到项目的位置。

  • SAR Creator项目构建插件的配置,因为SAR Creator可以适配各种平台,因此SAR Creator的构建流程通过插件的形式嵌入到不同平台的构建流程当中,并可以在插件中深度集成平台的相关能力。

SAR Creator项目配置文件通常叫做sar.config.js,这边以春节的摇签项目配置举例,项目的配置文件如下所示:

const path = require('path');
module.exports = {// 指定入口文件目录projectRoot: path.resolve(__dirname, 'game'),previewConfig: {previewDevtool: true,resolve: {alias: {// 别名,脚本中使用@lottery代替绝对路径,用来避免sar creator报错'@lottery': path.resolve(__dirname, './')}}}
};

插件通常在平台的配置文件中引入,因此插件的配置通常也在平台的配置文件中,此次春节活动是基于字节内的跨端框架平台开发,所以接下来会结合跨端框架平台做插件配置的功能介绍。

分包配置

跨端框架平台的项目会主动下发资源到用户手机,但是为了提高资源包下发的成功率,单包的限制通常在5M,因为如果我们的项目资源大于5M时,就需要进行拆包,在上面我们已经介绍过了Bundle分包,其能很好的将互动资源进行拆分并动态加载,但是一个Bundle包不一定有5M,因此为了让资源包收益最大化,一个资源包可以由几个Bundle包组成,这个拆分手动的话会很麻烦,因此我们通过工程配置在,构建完成后进行分包,配置信息如下:

const lotterySarConfig = {// ....../** 分包策略,构建才会生效 **/subPackages: {// 可以过滤掉一些包,比如测试包需要被剔除excludeBundles: ['test'],// 组合bundle包为gecko包的规则combineBundleRules: [{// 拆分到的gecko包名channelName: 'pitaya-lottery-game-2',// bundle包匹配符合条件的正则规则test: [/mascot/]},{channelName: 'pitaya-lottery-game',test: [/main-scene/, /resources/],preload: true,preloadPriority: 96}]}
};

内联配置

在Bundle包中,会存在各种config或者json配置文件,文件数量较多时,每次访问都需要请求一个链接地址,为了减少请求次数,我们可以通过配置插件构建,将每个Bundle包中的json文件合并成一个二进制文件,减少请求的次数和资源的大小,并且为了防止单个二进制文件太大,我们仍可以限制合并的二进制的文件大小,以确保不影响请求资源下载的速度,配置如下:

const lotterySarConfig = {// ....ejectOptions: {// bundle的config文件不生成disableGenConfigWhenInline: true,// group分组配置信息groupConfig: {// 针对 bundle 下 group 的体积限制,优先级更高groupPackingSizeLimitBundleConfig: {// 名为mascot的 bundle 下单个group限制400k大小 mascot: 400,// 同上resources: 400}},// 内置bundle文件的config配置到entry.ts里inlineConfig: {'main-scene': true,resources: true,mascot: true}},
}

预加载配置

跨端框架平台支持资源的预加载,为了配合平台特性,我们还可以在构建生成游戏的时候就配置Bundle里的资源支持预加载,然后在构建完成后就可以生成预加载的配置文件,可以使用户在打开容器时就可以让容器提前加载好配置文件里的资源,使项目内加载到资源的时候,能更快的加载资源,其配置如下:

const lotterySarPreloadUrlList = [];
const lotterySarConfig = {// ......// preload: {// 预加载资源前缀publicPath: `https://${CDN_DOMAIN}${GECKO_PREFIX}/pitaya-lottery-main/`,// 限制预加载资源个数limit: 300,// 限制预加载文件总体积, 默认就是3MsizeLimit: 3 * 1024, // 配置文件输出目录outputDir: 'merge-js/lottery',// 过滤资源的规则asset: {rules: [{// 匹配规则test: /.*/,// 可以匹配重写该资源是否加入 preload.json,返回 { enableMemory, url, priority } 或 nullrewrite: (item) => {if (item.url.endsWith('.png') ||item.url.endsWith('.jpg') ||item.url.endsWith('.jpeg') ||// 已经加入的不再次加入preloadlotterySarPreloadUrlList.includes(item.url)) {// 不写入预加载配置return;}lotterySarPreloadUrlList.push(item.url);item.enableMemory = true;// 写入预加载配置return item;}}]}}
}

最后预加载的配置文件如下所示:

{// 跨端框架页面路径"***/index/template.js": {"image": [{// 是否开启内存缓存"enableMemory": true,// 资源加载路径"url": "***/resource/image/back.bcd0a82e.png",// 资源大小"size": 280},// ....],"other": [{"enableMemory": true,"url": "***/main-scene/g_0.cc991.group","priority": 96,"size": 143296,"assetBundleType": "group"},// ......]}
}

依据跨端框架的页面路径,来预加载配置的URL链接以及优先级,能够在页面打开前就提前加载好资源内容。

开发实践

脚本编写

在资产平台右键我们可以创建默认脚本,脚本格式如下所示

a39feb4cb45bf606b323286cd4b93f21.png
// newscript.ts 脚本文件import { Script, ScriptUtil } from '@sar-creator/toolkit/engine/core';@ScriptUtil.Register('NewScript')
export default class NewScript extends Script {onStart() {const scene = this.world.getEntitiesByName('Scene')[0];if (scene) {// TODO:}}
}

SAR Creator 脚本的生命周期分为以下几个阶段:

  • onAwake:节点挂载时执行一次

  • onDestroy:节点销毁时执行

  • onPause:暂停时执行

  • onResume:恢复时执行

  • onStart:第一次帧动画开始前执行一次

  • onUpdate:每帧开始时执行

  • onLateUpdate:每帧结束时执行

我们常用的生命周期有onStartonUpdateonResume这个三个生命周期。

onStart是在节点首帧时激活一次,表明游戏已经可以开始运行,我们一般在此阶段动态加载资源,将获取到的资源添加到场景中,或者获取场景的某些节点实例。因为我们的项目是SAR Creator + 跨端框架组合,所以在跨端框架阶段初始化引擎的时候,我们会同步去获取服务端数据,当满足onStart触发以及数据获取成功两个条件时,我们一般会在脚本内依据数据初始化场景内容。

onUpdate会在节点的每帧渲染前触发一次,由requestAnimationFrame驱动,当我们需要变换场景中的元素的时候,就可以依靠每帧触发修改微小的变量,达到最终看起来连贯变换的样子,例如在摇签玩法中我们会依据陀螺仪的数据来确定签筒的状态,因此我们在此阶段每帧获取陀螺仪的数据,然后对其操作同步转换签筒的状态,让签筒有一种跟手的感觉。

onResume会在游戏暂停后重启时触发,一般来说当我们有些定时操作会在暂停阶段销毁,在恢复阶段触发,除此之外,当节点隐藏恢复时也会触发此阶段,当一个节点启动时播放动画,播放完成后隐藏,当恢复时需要重置动画状态并播放就可以在这个阶段进行。

预制体制作

当我们将层级面板中的节点拖拽到资产面板中就会自动生成预制体资产,预制体资产储存了这个节点的所有的数据以及依赖的资源信息。

aa49991b785f383f18cb353c4079af64.png

双击预制体资源,我们仍可以对预制体进行二次编辑等操作。

b1062bd3002fc95f22ce7c86b71cdfca.png

使用预制体资源可以帮我们可视化的预设大量的节点数据,我们可以通过直接加载制作的预制体,节省大量的实体修改参数配置等操作,从而提高我们的开发速度。

另外将场景中的非必要资源拆成预制体加载,可以有效提升主场景的加载速度,并渐进式加载其他装饰节点预制体到场景当中,并且可以依据用户手机性能,选择性加载不同复杂程度的预制体到场景当中。

例如在摇签玩法中,我们预设了不同的背景烟花以及签筒的预制体,使用时我们依据时机判断加载不同的烟花到场景当中,以及依据用户的手机性能,选择性加载要求更高性能的签筒还是性能要求更低的签筒。

c8683dfd43742295aef5fc4f47e83295.png

动态加载

在项目搭建中我们已经介绍了Bundle的配置方式,用户可以将文件夹配置成动态资源包,那么加载动态资源包我们提供了资源管理器assetManager挂载在world上,例如加载一个预制体资源如下所示:

const { bundle, error: bundleError
} = await this.world.assetManager.loadBundle('resources');if(!bundle || errror) throw bundleErrorconst {asset,error: prefabError
} = await bundle.load<Entity>(`prefabs/fireworks/${prefabName}.prefab`);if (!asset?.get?.() || prefabError) throw prefabError;const entity = asset.get() as Entity

我们需要先使用loadBundle获取到这个Bundle包的实例,loadBundle支持传入Bundle的名称或者链接,拿到Bundle实例后,我们按照资源在bundle包中的路径加载,就可以获得到一个asset资产对象,asset调用get方法可以获取当前加载资产的实例,例如加载预制体获取到Entity实例。

另外当我们加载图片资源时,我们从资产面板可以看到图片的texture虚拟资产Texture对象,如果我们想要直接加载图片的Texture对象时,就可以在加载图片的路径中拼接上index.texture,例如下所示:

bf02cc73a1a56cebb3522554db65a6b8.png

const { 
  bundle, 
  error: bundleError
} = await this.world.assetManager.loadBundle('resources');

if(!bundle || errror) throw bundleError

const {
  asset,
  error: textureError
} = await bundle.load<Texture>(`texture/lamp/rect.png/index.texture`);

 if (!asset?.get?.() || textureError) throw textureError;
 
 const texture = asset.get() as Texture


fda486398ea9723832b83f1a2de896ea.png
const { bundle, error: bundleError
} = await this.world.assetManager.loadBundle('resources');if(!bundle || errror) throw bundleErrorconst {asset,error: textureError
} = await bundle.load<Texture>(`texture/lamp/rect.png/index.texture`);if (!asset?.get?.() || textureError) throw textureError;const texture = asset.get() as Texture

未来展望

在过去的一年中,我们的SAR Creator产品经历了三个重要的大版本更新,分别是1.0、1.1、以及1.2,三个版本的迭代都是我们基于用户需求并不断优化用户体验推出来的阶段性版本。

在三个版本的迭代中,我们满足了研发同学的一些重要需求,例如脚本配置、bundle分包、性能优化等;增添了一些新功能,例如动画编辑器、VFX Particle、SAR Creator Launcher等;优化了SAR Creator的使用体验,例如多语言版本、材质属性分组、资产预览面板等。

基于过去一年的迭代,SAR Creator为春节的活动的开发带来了稳定的功能支持,在2024年中,SAR Creator将会持续优化引擎性能以及编辑器的易用性。

除此之外动画将是编辑器能力的核心,在2024年中我们将会不断扩展动画编辑器的能力,使用SAR Creator能够实现更加丰富的动画编辑功能,简单的动画元素将直接可以使用编辑器完成开发和预览。

团队介绍

我们是抖音前端架构-互动体验技术团队,主要为字节跳动业务提供互动技术解决方案。技术产品包含面向互动 / 小游戏研发场景的 SAR Creator、高性能动效渲染引擎 Simple Engine、互动场景端能力套件 AnnieX 互动容器

在这些技术建设与业务落地上,和抖音前端-互动创作团队跨端框架团队、开放平台小游戏团队、用户增长-激励前端团队一同推进,不断探索字节跳动应用生态下的创新业务形态。

下期预告

下期主题为渲染技术与实践,为了满足视觉和性能的两个要求,我们在渲染能力上提供了多种方法在适合的场景使用,最终达到了极为优秀的效果,敬请期待。

往期回顾

2024 抖音欢笑中国年(一):招财神龙互动技术揭秘

2024 抖音欢笑中国年(二):AnnieX互动容器创新玩法解析

相关文章:

2024 抖音欢笑中国年(三):编辑器技巧与实践

前言 本次春节活动中&#xff0c;我们大部分场景使用内部的 SAR Creator互动方案来实现。 SAR Creator 是一款基于 TypeScript 的高性能、轻量化的互动解决方案&#xff0c;目前支持了Web和字节内部跨端框架平台&#xff0c;服务于字节内部的各种互动业务&#xff0c;包括但不限…...

Python学习入门(1)——基础语句(二)

14. 迭代器和迭代协议 在Python中&#xff0c;迭代器是支持迭代操作的对象&#xff0c;即它们可以一次返回其成员中的一个。任何实现了 __iter__() 和 __next__() 方法的对象都是迭代器。 class Count:def __init__(self, low, high):self.current lowself.high highdef __i…...

vue 百度地图 使用 vue-baidu-map 进行当前位置定位和范围展示

vue 百度地图 使用 vue-baidu-map 进行当前位置定位和范围展示&#xff08;考勤打卡&#xff09; 一、创建百度地图账号&#xff0c;获取秘钥二、 引入插件1、安装vue-baidu-map2、在main.js中引入 三、 简单使用 最近写项目的时候&#xff0c;做到了考勤打卡的模块内容&#x…...

使用idea运行程序,发现控制台的中文出现乱码

修改UTF-8发现没有效果&#xff0c;寻找.idea文件夹的encodings.xml文件&#xff0c;将里面的UTF-8全部变成GBK....

基于javassm实现的大学生兼职信息系统

开发语言&#xff1a;Java 框架&#xff1a;ssm JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&…...

O2OA开发平台如何查看数据表结构?

在访问后端api地址&#xff0c;页面最下方有列示平台的各个服务&#xff0c;点击进入可查看具体的表内容 后端api地址&#xff1a; http://{hostIP}/x_program_center/jest/list.html 其中&#xff1a;{hostIP}为中心服务器所在域名或者IP地址 如下图&#xff1a;...

心理测评性格测试矩阵版h5微信抖音QQ快手小程序app开源版开发

心理测评性格测试矩阵版h5微信抖音QQ快手小程序app开源版开发 支持SAAS、支持独立加密、支持独立开源、价格不同。 自带题库数据&#xff0c;后台一键初始&#xff0c;支持自己上传题目 心理测评 微信公众号微信小程序抖音小程序可打包APP 支持单题、跳跃题、计分题、因子题、…...

【蓝桥杯】十六进制转八进制 C++实现

1.题目信息 时间限制&#xff1a;1.0s 内存限制&#xff1a;512.0MB 问题描述 给定n个十六进制正整数&#xff0c;输出它们对应的八进制数。 输入格式 输入的第一行为一个正整数n &#xff08;1<n<10&#xff09;。 接下来n行&#xff0c;每行一个由09、大写字母AF组成…...

明明设置数字居中对齐,为什么excel的数字却不居中?

有时候在excel里&#xff0c;选中数据&#xff0c;设置对齐方式 左右居中&#xff0c;然而&#xff0c;数字却怎么都不居中&#xff0c;为什么呢&#xff1f; 1.按快捷键Ctrl1&#xff0c;打开单元格自定义格式对话框&#xff0c;看到是初始界面是在数字的会计专用&#xff0c;…...

深入解析API技术:原理、实现与应用

在现代软件开发中&#xff0c;API&#xff08;应用程序接口&#xff09;扮演着至关重要的角色。API 允许不同的软件应用程序和系统之间进行通信和数据交换&#xff0c;从而构建出更加高效、灵活和可扩展的软件解决方案。本文将深入解析API技术的原理、实现方法&#xff0c;并附…...

C语言——数组指针变量

一、什么是数组指针 数组指针变量是指向数组的指针&#xff0c;它可以用来遍历数组元素、进行数组操作以及作为函数参数传递数组等操作。在C语言中&#xff0c;数组名本身就是数组的首地址&#xff0c;因此数组指针可以指向数组的首地址。 数组指针变量的基本形式&#xff1a…...

Redis的过期策略与内存淘汰机制原理及实践

Redis作为高性能的键值存储系统&#xff0c;其对数据过期与内存管理的设计直接影响到系统的性能与资源利用率。本文将以生动的比喻、通俗的语言&#xff0c;深入剖析Redis的过期策略与内存淘汰原理&#xff0c;助您全面理解数据在Redis中的生命周期管理艺术。 一、Redis过期策…...

【24届数字IC秋招总结】提前批面试经验1——小米、百度昆仑芯、长鑫存储

文章目录 前言一、小米-SOC验证工程师1.1 面试问题二、百度昆仑芯-芯片验证工程师2.1 一面面试问题2.2 二面面试问题三、长鑫存储-数字电路前言 提前批面试公司:小米、百度昆仑芯、长鑫存储 一、小米-SOC验证工程师 面试时间:7.23 周末 1.1 面试问题 1、 问研究生项目,自…...

第7章、ReactRedux 实战 - 登录注册验证;

一、登录注册认证系统课程介绍&#xff1b; 1、基本概念&#xff1b; &#xff1b; 2、代码&#xff1b; 二、搭建前端环境&#xff1b; 1、基本概念&#xff1b; &#xff1b; 2、代码&#xff1b; 三、搭建后端环境&#xff1b; 1、基本概念&#xff1b; &#xff1…...

16路HDMI+AV流媒体IPTV高清编码器JR-3216HD

产品简介&#xff1a; JR-3216HD 16路高清HDMIAV编码器是专业的高清音视频编码产品&#xff0c;该产品具有支持16路高清HDMI音视频采集功能&#xff0c;16路标清AV视频采集功能&#xff0c;16路3.5MM独立外接音频输入&#xff0c;编码输出双码流H.264格式&#xff0c;音频MP3/…...

vscode 配置文件settings.json和c_cpp_properties.json的作用

前言 在 Visual Studio Code (VSCode) 中&#xff0c;settings.json 和 c_cpp_properties.json 都是配置文件&#xff0c;它们分别用于不同的目的。 settings.json settings.json 文件是 VSCode 的用户或工作区设置文件。它允许你自定义 VSCode 的各种行为和外观。 用户设置…...

【postgresql 基础入门】入门教程成形了,八大章节,涵盖库,表,事务,约束,数据类型,聚集函数,轻松入门

Postgresql 基础入门 ​专栏内容&#xff1a; postgresql内核源码分析手写数据库toadb并发编程 个人主页&#xff1a;我的主页 管理社区&#xff1a;开源数据库 座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物. 序言 Postg…...

【计算机毕业设计】人事管理系统——后附源码

&#x1f389;**欢迎来到我的技术世界&#xff01;**&#x1f389; &#x1f4d8; 博主小档案&#xff1a; 一名来自世界500强的资深程序媛&#xff0c;毕业于国内知名985高校。 &#x1f527; 技术专长&#xff1a; 在深度学习任务中展现出卓越的能力&#xff0c;包括但不限于…...

OceanBase V4.2 MySQL模式下,如何通过DBLINK实现跨数据源访问

概述 跨数据源访问可通过 DBLINK&#xff08;以下简称DBLINK&#xff09;实现&#xff0c;从而使得业务代码能够像访问本地数据库一样轻松访问远端数据库。原先&#xff0c;DBLINK主要服务于Oracle模式&#xff0c;但由于OceanBase 的MySQL模式租户同样存在访问远端数据库的需…...

再谈C语言——理解指针(一)

内存和地址 内存 在讲内存和地址之前&#xff0c;我们想有个⽣活中的案例&#xff1a; 假设有⼀栋宿舍楼&#xff0c;把你放在楼⾥&#xff0c;楼上有100个房间&#xff0c;但是房间没有编号&#xff0c;你的⼀个朋友来找你玩&#xff0c; 如果想找到你&#xff0c;就得挨个房…...

day21-二叉树part08

235. 二叉搜索树的最近公共祖先 相对于 二叉树的最近公共祖先 本题就简单一些了&#xff0c;因为 可以利用二叉搜索树的特性无需全部遍历。特点&#xff1a;当前节点在p&#xff0c;q节点之前则必为最近公共祖先 class Solution {public TreeNode lowestCommonAncestor(TreeNo…...

【WPF应用42】WPF中的 GroupBox 控件详解

在 Windows Presentation Foundation (WPF) 中&#xff0c;控件是构建用户界面 (UI) 的基础。WPF 提供了丰富的控件库&#xff0c;其中包括 GroupBox 控件&#xff0c;它用于将相关的 UI 元素组织到逻辑分组中。在本博客文章中&#xff0c;我们将详细介绍 GroupBox 控件的功能、…...

LeetCode-72. 编辑距离【字符串 动态规划】

LeetCode-72. 编辑距离【字符串 动态规划】 题目描述&#xff1a;解题思路一&#xff1a;动规五部曲解题思路二&#xff1a;动态规划【版本二】解题思路三&#xff1a;0 题目描述&#xff1a; 给你两个单词 word1 和 word2&#xff0c; 请返回将 word1 转换成 word2 所使用的最…...

多张静图合成gif怎么做?一键极速合成gif

图片的格式有很多种&#xff0c;通常分为静态图片和动态图片。而动态图片基本上都是gif格式&#xff0c;想要把其他格式的静图变成gif格式动图的时候要怎么操作呢&#xff1f;通过使用gif动画图片&#xff08;https://www.gif.cn/&#xff09;制作网站&#xff0c;上传jpg、png…...

Es中bool 查询中的四个(must must_not should filter)

1.must :相当于and 2.must_not :相当于not 3.should:相当于or 4. filter:过滤 gte 大于 gt大于 lte小于等于 lt小于 使用示例&#xff1a; {“bool”:{“must”:{“match”:{“title”:”how to make millons “}},“must_not”:{“match”:{“tag”:”spam“}},“should”:[{…...

Docker容器嵌入式开发:Docker Ubuntu18.04配置mysql数据库

在 Ubuntu 18.04 操作系统中安装 MySQL 数据库的过程。下面是安装过程的详细描述&#xff1a; 首先&#xff0c;使用以下命令安装 MySQL 服务器&#xff1a; sudo apt install mysql-server系统会提示是否继续安装&#xff0c;按下 Y 键确认。 安装过程中&#xff0c;系统会…...

C++类和对象中上篇

1.类的6个默认成员函数 如果一个类中什么成员都没有&#xff0c;那就简称他为空类。 空类中真的什么都没有吗&#xff1f;并不是&#xff0c;任何类在什么都不写时&#xff0c;编译器会自动生成以下6个默认成员函数。 默认成员函数&#xff1a;用户没有显式实现&#xff0c;…...

基于linux进一步理解核间通讯

芯片架构分为同构和异构: 如下图TC397: 如下图TDA4: 如下图STM32MP157: 非对称多处理结构(AMP): AMP 结构是指每个内核运行自己的 OS 或同一 OS 的独立实例&#...

应用实战|从头开始开发记账本2:基于模板快速开始

上期视频我们创建好了BaaS服务的后端应用。从这期视频开始&#xff0c;我们将从头开发一个互联网记账本应用。本期视频我们介绍一下如何使用模板快速开启我们的应用开发之旅。 应用实战&#xff5c;从头开始开发记账本2&#xff1a;基于模板快速开始 相关代码 本期视频我们介绍…...

学习前端第二十天(条件分支:if 和 ‘?‘;逻辑运算符)

一、条件分支 if (…) 语句会计算圆括号内的表达式&#xff0c;并将计算结果转换为布尔型。 if(...) 语句计算括号里的条件表达式&#xff0c;如果计算结果是 true&#xff0c;就会执行对应的代码块{ }。 if 语句有时会包含一个可选的 “else” 块。如果判断条件不成立&…...

小说做任务赚钱的网站/劳动局免费培训电工

阅读全文 类别&#xff1a;Sqlite 查看评论文章来源:http://hi.baidu.com/luchaoshuai/blog/item/e63e83ea7bf8dbd6d539c9ac.html转载于:https://www.cnblogs.com/luchaoshuai/archive/2008/07/08/1243021.html...

云南旅游网站建设公司/搜狗收录查询

window对象常见事件 调整窗口大小 window.onresize window.onresize为调整窗口大小触发事件&#xff0c;通俗来讲就是当调整浏览器可视区的大小的时候触发onresize事件。 使用方法如下 <body><script>window.addEventListener(resize, function () {console.lo…...

最新流行网站开发技术/最新推广方法

前叙&#xff1a;有灵魂的程序都是每一个程序员的最终目标。TensorFlow了解下&#xff1f; 打算花几个月学机器学习&#xff0c;TensorFlow是很好的选择&#xff0c;折腾了会环境&#xff0c;略有心得分享下。 环境&#xff1a;win10 Python&#xff1a;3.6.5 TensorFlow-GPU&…...

我想做/seo诊断

HTMLTestRunner下载地址&#xff1a; python 2: http://tungwaiyip.info/software/HTMLTestRunner.html python 3:http://pan.baidu.com/s/1dEZQ0pz 下载后放到路径&#xff1a;${python}\Lib\site-packages\ 在cmd引入HTMLTestRunner 不报错说明成功 3.方法一&#xff1a; …...

内链wordpress/百度手机助手最新版下载

http://news.cnblogs.com/n/37759/转载于:https://www.cnblogs.com/kexb/p/3792412.html...

做网站推广的方法有哪些/java培训班

案例介绍&#xff1a; 我们在日常生活中&#xff0c;经常与朋友们玩猜数字的游戏&#xff0c;非常的有趣。现在我们通过java把这个猜数字游戏编写出来。 猜数字案例是要完成什么样的功能呢&#xff1f;顾名思义&#xff0c;这个游戏就是你出个数字、我来猜。 游戏操作如下&…...