资讯动态

Unity粒子系统与UI交互实战:祈愿场景开发全解析

发布时间:2026/10/14 4:35:37 来源:尧图企业网站定制
1. 项目缘起与整体设计思路1.1 这个项目到底在做什么第一次看到“阿索拉星之祈愿”这个名字我脑子里蹦出来的画面是那种带点复古日系味道的星空祈愿场景——一个角色站在星空下对着流星许愿周围有粒子光效、有缓缓旋转的星轨、有飘落的许愿签。后来拿到项目文件一看果然八九不离十这是一个用Unity做的轻量级互动场景Demo核心玩法就是“祈愿”这个动作玩家点击屏幕上的祈愿按钮触发一段粒子动画然后随机获得一句祈愿文案配合音效和UI反馈形成一个完整的情绪闭环。说白了它不是一个完整的游戏更像是一个氛围感交互小场景。但恰恰是这种“小而美”的东西最能体现一个Unity开发者对细节的把控能力。因为大项目有大项目的架构撑着小场景反而每一处都得自己抠——粒子怎么调、UI怎么动、音效什么时候进、文案怎么随机才不显得生硬这些全是硬功夫。这个项目适合谁看我觉得有三类人值得花时间研究第一类是刚学完Unity基础、想找个完整小项目练手的初学者因为这个项目涉及了Unity最核心的几个模块——场景搭建、UI系统、粒子系统、脚本交互、音频管理麻雀虽小五脏俱全第二类是想做氛围感交互场景的独立开发者比如做治愈系小工具、互动贺卡、轻量级叙事Demo的人这个项目的结构可以直接拿来改第三类是对“祈愿”这个主题有情感共鸣的普通玩家想看看这种场景在技术层面是怎么实现的。1.2 为什么选择Unity而不是其他引擎这个问题我在做这个项目之前认真想过。如果只是做一个2D的祈愿界面其实用Web技术HTMLCSSJS也能做而且部署更方便。但最终选Unity核心原因有三个。第一个原因是粒子系统的成熟度。祈愿场景的灵魂在于粒子效果——星光闪烁、流星划过、光点汇聚、许愿签飘落这些效果在Unity的Particle System里都有现成的模块可以调而且性能优化做得很好。如果用Web做要么用Canvas手写粒子逻辑性能差、效果糙要么引入Three.js学习成本高、调试麻烦。Unity的粒子系统是可视化编辑的调参数所见即所得这对做氛围感场景来说太重要了。第二个原因是跨平台能力。这个项目虽然现在跑在PC上但Unity天然支持导出到移动端、WebGL、甚至主机平台。如果后续想把它做成手机上的祈愿小应用或者嵌入到某个网页里Unity的构建管线可以直接搞定不需要重写逻辑。这种“一次开发、多端部署”的能力对于独立开发者来说非常关键。第三个原因是音频与动画的同步控制。祈愿场景需要音效和动画精确配合——按钮按下的瞬间要有“叮”的一声粒子爆发的时候要有“嗡”的共鸣音文案出现的时候要有轻柔的背景音渐入。Unity的AudioSource和Animator可以通过脚本精确控制播放时机而且支持音频混音器做动态调整。这种精细的同步控制在Web技术栈里实现起来要麻烦得多。当然Unity也不是没有缺点。最明显的就是包体大小——一个空Unity项目打包出来至少几十兆如果只是做一个简单的祈愿页面确实有点“杀鸡用牛刀”。但考虑到这个项目后续可能扩展成更复杂的互动场景这个代价是可以接受的。1.3 整体架构是怎么搭的项目的架构我采用了轻量级MVC变体的思路。不是那种重型框架而是根据场景需求做了简化。具体来说分三层数据层负责管理祈愿文案库、用户祈愿记录、场景配置参数。文案库我用了一个ScriptableObject来存储每一条祈愿文案包含文本内容、稀有度等级、对应的粒子颜色预设。这样做的好处是策划或者我自己可以在Inspector面板里直接增删改文案不需要动代码。用户祈愿记录用PlayerPrefs存储虽然简单但够用毕竟这个场景不需要复杂的存档系统。逻辑层是核心交互控制包括祈愿触发判定、随机文案抽取、粒子效果调度、音效播放控制。这一层我写了一个WishManager作为主控制器它持有对UI、粒子、音频模块的引用通过事件系统解耦各模块之间的通信。比如当祈愿触发时WishManager会派发一个OnWishTriggered事件UI模块监听这个事件来播放按钮动画粒子模块监听这个事件来触发粒子爆发音频模块监听这个事件来播放音效。这样各模块之间不需要互相引用后续增删功能都很方便。表现层包括UI界面、粒子效果、场景环境星空背景、地面、装饰物。UI用UGUI做粒子用Particle System场景环境用简单的3D模型加材质。表现层不包含任何业务逻辑只负责“收到指令就播放效果”。这种分层方式的好处是可测试性和可扩展性。比如我想测试“连续祈愿十次”的逻辑只需要在逻辑层模拟十次事件派发不需要真的去点十次按钮。又比如我想换一套粒子效果只需要替换表现层的预制体逻辑层完全不用改。注意ScriptableObject存储文案库时记得给每条文案加一个唯一ID后续如果要做“已解锁文案”的功能ID就是索引依据。我一开始没加后来想加收集系统的时候不得不回头补浪费了不少时间。2. 核心细节解析与实操要点2.1 祈愿文案的随机抽取算法祈愿文案的随机抽取看似简单但如果只是用Random.Range从数组里随便取一个体验会很差——玩家可能连续抽到同一条文案或者稀有文案永远抽不到。我在这个项目里用了一套加权随机去重缓冲的方案。先说加权随机。每条祈愿文案有一个稀有度等级分为普通、稀有、史诗三档。普通文案权重为60稀有文案权重为30史诗文案权重为10。抽取的时候不是直接随机索引而是先计算总权重然后生成一个0到总权重之间的随机数再遍历文案列表累加权重直到累加值超过随机数就选中当前文案。这个算法的核心代码如下public WishText GetRandomWish() { int totalWeight 0; foreach (var wish in wishList) { totalWeight wish.weight; } int randomValue Random.Range(0, totalWeight); int currentWeight 0; foreach (var wish in wishList) { currentWeight wish.weight; if (randomValue currentWeight) { return wish; } } return wishList[wishList.Count - 1]; }这段代码的逻辑很直白权重越大的文案在总权重区间里占的范围越大被随机数命中的概率就越高。比如普通文案权重60稀有30史诗10总权重100那么随机数落在0-59就是普通60-89就是稀有90-99就是史诗。这样既保证了随机性又控制了稀有文案的出现频率。但光有加权随机还不够因为玩家可能连续抽到同一条普通文案体验上会觉得“怎么又是这个”。所以我加了一个去重缓冲队列每次抽到一条文案后把它加入一个“最近抽取”队列队列长度为3。下一次抽取时如果抽到的文案已经在队列里就重新抽一次最多重试3次。这样基本能避免连续重复同时不会完全破坏随机性。实操心得去重缓冲队列的长度不要设太大3到5比较合适。设太大了会导致稀有文案被“挤”掉——因为稀有文案本来数量就少如果队列太长每次抽到稀有文案都被缓冲掉玩家反而更难抽到。我一开始设了10测试的时候发现史诗文案几乎抽不出来后来改成3就正常了。2.2 粒子系统的参数调优祈愿场景的粒子效果是整个项目的视觉核心我用了三个Particle System分别负责不同层次的效果星光粒子负责背景的星星闪烁汇聚粒子负责祈愿时从四周向中心汇聚的光点爆发粒子负责祈愿完成时的光效爆发。星光粒子的调优关键是“若隐若现”的感觉。如果星星一直亮着会显得很假如果闪烁太快又会显得焦躁。我的参数设置是Start Lifetime设为3到5秒随机Start Speed设为0星星不需要移动Start Size设为0.05到0.15随机Color over Lifetime用一条Alpha曲线控制透明度从0渐变到1再渐变到0形成一个柔和的闪烁周期。Emission Rate设为10Shape用Box覆盖整个星空背景区域。汇聚粒子的难点在于“从四周向中心移动”的轨迹控制。Particle System自带的Velocity over Lifetime只能做直线运动要做向中心汇聚的效果需要用Force over Lifetime配合一个指向中心的力场。具体做法是把Shape设为Sphere半径设大一点比如5然后Force over Lifetime的Z轴设为一个负值指向中心同时配合Limit Velocity over Lifetime把最大速度限制住防止粒子冲过中心。这样粒子就会从球面各处向中心加速汇聚到中心附近速度被限制住形成“汇聚但不穿透”的效果。爆发粒子的关键是“一瞬间炸开”的冲击感。Start Lifetime设短一点0.5到1秒Start Speed设大一点5到10Start Size设小一点0.1到0.3Emission用Burst模式在时间0秒时发射50到80个粒子。Color over Lifetime用一条从亮白到透明的渐变曲线Simulation Space设为World这样粒子爆发后不会跟着物体移动。另外记得把Renderer的Material换成Additive的粒子材质这样光效叠加起来会更亮更梦幻。粒子系统核心参数推荐值作用星光粒子Start Lifetime3-5秒随机控制闪烁周期星光粒子Emission Rate10控制星星密度汇聚粒子Force over LifetimeZ轴负值控制汇聚方向汇聚粒子Limit Velocity2-3防止穿透中心爆发粒子Start Speed5-10控制爆发力度爆发粒子Burst Count50-80控制爆发密度注意粒子系统的Renderer模块里Sorting Layer和Order in Layer要设置好否则粒子可能会被UI遮挡或者遮挡UI。我的做法是把粒子放在单独的Sorting Layer里UI放在更高的Layer这样粒子永远在UI下面不会挡住按钮。2.3 UI交互的反馈设计祈愿按钮的交互反馈我做了三层按下反馈、触发反馈、结果反馈。按下反馈是按钮被按下的瞬间按钮缩放从1变成0.95同时颜色稍微变暗持续0.1秒后恢复。这个反馈的目的是让玩家感觉到“我按到了”而不是按下去没反应。实现方式是用UGUI的Button组件自带的Transition把Transition设为Scale然后配置Normal和Pressed状态的缩放值。但UGUI自带的Scale过渡有点生硬所以我后来改用脚本控制在OnPointerDown里用DOTween做缩放动画OnPointerUp里恢复这样过渡更平滑。触发反馈是祈愿动作被确认后按钮会有一个“脉冲”效果——先快速放大到1.1然后弹回1.0同时按钮周围出现一圈扩散的光环。这个光环我用了一个Image组件初始Scale为0.5Alpha为1然后在0.3秒内Scale变到2.0Alpha变到0形成一个扩散消失的效果。这个反馈的目的是让玩家感觉到“祈愿已经生效了”给一个明确的确认信号。结果反馈是祈愿文案出现时的动画。文案不是直接显示出来的而是从下方缓缓升起同时Alpha从0渐变到1持续0.5秒。文案的背景框有一个轻微的呼吸效果——Scale在1.0到1.02之间循环周期2秒。这个反馈的目的是让玩家的注意力自然地被引导到文案上而不是突然跳出来吓一跳。实操心得UI动画的时间控制很关键。按下反馈要快0.1秒以内否则会觉得迟钝触发反馈要干脆0.3秒左右否则会觉得拖沓结果反馈可以慢一点0.5到0.8秒给玩家留出阅读和感受的时间。我一开始把结果反馈也设成了0.2秒测试的时候感觉文案“闪了一下就没了”完全没有沉浸感后来改成0.6秒就舒服多了。2.4 音频系统的分层管理音频在这个项目里不是背景装饰而是情绪引导的重要工具。我用了三个AudioSource分别管理背景音、交互音效、祈愿音效通过AudioMixer做统一管理。背景音是一个循环播放的轻柔环境音音量控制在-20dB左右不能太响否则会盖住音效。交互音效是按钮按下的“叮”声音量-10dB短促清脆。祈愿音效是祈愿触发时的“嗡”声加上粒子爆发时的“哗”声音量-5dB是整个场景里最响的声音因为它是情绪高潮。AudioMixer的好处是可以做动态混音。比如当祈愿音效播放时我可以让背景音自动降低3dB等祈愿音效播完再恢复这样祈愿音效会更突出不会被背景音淹没。实现方式是在AudioMixer里给背景音轨道加一个Duck Volume效果侧链设为祈愿音效轨道这样祈愿音效一响背景音自动闪避。// 通过脚本控制AudioMixer的参数 public AudioMixer mainMixer; public void OnWishTriggered() { // 祈愿音效播放时背景音降低 mainMixer.SetFloat(BGMVolume, -23f); StartCoroutine(RestoreBGMAfterDelay(2f)); } private IEnumerator RestoreBGMAfterDelay(float delay) { yield return new WaitForSeconds(delay); mainMixer.SetFloat(BGMVolume, -20f); }注意AudioMixer的参数暴露要在Inspector里手动设置把需要脚本控制的参数右键选择“Expose to Script”然后才能在代码里用SetFloat调用。我一开始忘了暴露参数代码里怎么调都没反应排查了半天才发现是这个问题。3. 实操过程与核心环节实现3.1 场景搭建的完整流程场景搭建我分四步走环境搭建、灯光布置、相机设置、氛围装饰。环境搭建先创建一个Plane作为地面材质用一个深蓝色的渐变贴图模拟夜空下的地面。然后在场景上方创建一个巨大的Sphere作为天空盒材质用Cubemap贴图是一张星空图。天空盒的材质要设为Skybox然后在Lighting设置里把Skybox Material指向它。这样整个场景就有了星空背景。灯光布置用了一盏Directional Light作为主光源颜色偏冷蓝强度0.5角度调低一点模拟月光。另外在场景中心上方加了一盏Point Light颜色偏暖黄强度1.0范围10作为祈愿区域的焦点光。这盏Point Light的强度会随着祈愿动作动态变化——祈愿触发时强度升到2.0然后慢慢降回1.0形成“祈愿时亮了一下”的效果。相机设置用了一个Perspective相机FOV设为60位置在场景中心偏上一点角度稍微向下俯视。相机上加了一个Post Processing Layer用了Bloom效果让亮部有光晕、Vignette效果让画面四周变暗聚焦中心、Color Grading效果把整体色调调冷。这三个后处理效果叠加起来氛围感直接拉满。氛围装饰加了一些简单的3D物体——几块石头、几根柱子、一些飘浮的光点。石头和柱子用ProBuilder快速建模材质用深色岩石贴图。飘浮光点用Particle System做参数和星光粒子类似但移动速度更慢范围更小集中在祈愿区域周围。实操心得Post Processing的Bloom效果参数要调好Threshold设0.8到1.0Intensity设0.5到1.0太强了会糊成一片太弱了没效果。我试了好几组参数最后用的是Threshold 0.9、Intensity 0.7配合粒子的Additive材质光晕效果刚刚好。3.2 祈愿交互的脚本实现祈愿交互的核心脚本是WishManager它负责协调所有模块。我把它拆成几个关键方法TriggerWish()、PlayWishEffects()、ShowWishText()、ResetWishState()。TriggerWish()是入口方法绑定在祈愿按钮的OnClick事件上。它首先检查当前是否正在祈愿中防止连点然后设置isWishing true派发OnWishTriggered事件启动协程WishSequence()。public void TriggerWish() { if (isWishing) return; isWishing true; OnWishTriggered?.Invoke(); StartCoroutine(WishSequence()); } private IEnumerator WishSequence() { // 第一阶段汇聚粒子播放 yield return new WaitForSeconds(1.0f); // 第二阶段爆发粒子播放 音效 PlayWishEffects(); yield return new WaitForSeconds(0.5f); // 第三阶段显示文案 WishText wish GetRandomWish(); ShowWishText(wish); yield return new WaitForSeconds(2.0f); // 第四阶段重置状态 ResetWishState(); }PlayWishEffects()负责触发粒子爆发和音效播放。它通过事件系统通知粒子模块和音频模块而不是直接引用它们。这样如果后续要换粒子效果或者音效只需要改对应模块的监听逻辑WishManager不用动。ShowWishText()负责显示祈愿文案。它从GetRandomWish()拿到文案数据然后设置UI文本、调整文本颜色根据稀有度、播放文字动画。稀有文案的颜色是金色普通文案是白色史诗文案是紫色带发光效果。ResetWishState()把isWishing设回false重置粒子系统隐藏文案UI让场景回到待机状态。注意协程里的WaitForSeconds时间要跟粒子效果的实际时长匹配。我一开始设的汇聚粒子播放1秒但实际粒子从四周汇聚到中心需要1.5秒导致爆发粒子在汇聚还没完成的时候就炸了效果很割裂。后来把等待时间改成1.5秒就对了。调这个时间的时候可以先把粒子效果单独播放一遍用秒表掐一下实际时长。3.3 文案库的配置与管理文案库我用ScriptableObject存储创建了一个WishTextData类继承自ScriptableObject里面包含一个ListWishText。每条WishText包含以下字段[System.Serializable] public class WishText { public string id; public string content; public WishRarity rarity; public int weight; public Color textColor; public AudioClip specialSound; } public enum WishRarity { Common, Rare, Epic }在Unity编辑器里我创建了一个WishTextDatabase资产然后在Inspector面板里手动填入文案。目前填了大概30条普通20条、稀有8条、史诗2条。文案内容我写的是那种带点诗意但不矫情的句子比如“愿你的每个明天都比今天更温柔”、“星光不问赶路人时光不负有心人”之类的。实操心得文案的权重不要设得太极端。我一开始普通文案权重100、稀有10、史诗1结果测试的时候抽了50次才出一次史诗玩家根本感受不到稀有文案的存在。后来改成普通60、稀有30、史诗10大概每10次能出1次史诗这个频率比较合适——既不会烂大街也不会让人觉得“这游戏是不是没有史诗”。3.4 性能优化与打包设置这个项目虽然小但性能优化不能马虎。我做了三件事粒子数量控制、Draw Call合并、纹理压缩。粒子数量控制方面星光粒子最多同时存在200个汇聚粒子最多100个爆发粒子最多80个。超过这个数量就自动回收最早的粒子。Particle System的Max Particles参数直接设这个上限超过就自动停止发射。Draw Call合并方面场景里的静态物体石头、柱子都勾选了StaticUnity会自动做Static Batching。动态物体粒子、UI用Material Instance共享材质减少材质切换。最终Draw Call控制在50以内对于这种小场景来说完全够用。纹理压缩方面星空背景的Cubemap用了ASTC 6x6压缩UI贴图用了Sprite Atlas打包粒子材质用了最小的纹理尺寸64x64。打包出来的APK大概30兆左右对于一个Unity项目来说算比较轻量了。打包设置里我关掉了不必要的功能模块比如VR、AR、物理引擎的高级特性只保留了核心的渲染、音频、UI模块。Player Settings里把Color Space设为Linear颜色更准确Api Compatibility Level设为.NET Standard 2.0兼容性更好Scripting Backend用IL2CPP性能更好。优化项具体措施效果粒子数量Max Particles限制防止粒子过多导致卡顿Draw CallStatic Batching 材质共享Draw Call控制在50以内纹理压缩ASTC Sprite Atlas包体控制在30兆左右模块裁剪关闭VR/AR/高级物理减少包体和内存占用4. 常见问题与排查技巧实录4.1 粒子效果不显示或显示异常这是我在开发过程中遇到最多的问题。粒子不显示的原因通常有三个材质问题、渲染层级问题、生命周期问题。材质问题最常见。Particle System的Renderer模块里Material如果用了不支持的Shader比如Standard Shader粒子会显示成粉色方块或者完全不显示。正确的做法是用Particles/Standard Unlit Shader或者用Additive/Premultiply的粒子专用Shader。我一开始用了Standard Shader粒子全是粉色方块排查了半小时才发现是材质问题。渲染层级问题也很常见。如果粒子的Sorting Layer设成了Default而UI的Sorting Layer设成了UI那么粒子会被UI遮挡。解决方法是给粒子单独设一个Sorting Layer层级在UI之下、背景之上。或者把粒子的Renderer的Order in Layer设成一个负值让它排在UI后面。生命周期问题比较隐蔽。如果Start Lifetime设得太短比如0.1秒粒子刚发射就消失了看起来就像没显示。或者Emission Rate设成了0粒子根本不发射。排查的时候可以先把Start Lifetime设成10秒Emission Rate设成100看看粒子到底有没有在发射确认后再调回正常值。排查技巧在Scene视图里选中Particle System勾选“Simulate Layers”里的对应层级可以在编辑模式下预览粒子效果不用运行游戏就能调试。这个功能帮我省了很多时间。4.2 音频播放延迟或不同步音频延迟是Unity开发里的经典问题。我遇到的情况是按钮按下去之后音效要过0.2秒才响感觉很不跟手。排查后发现原因是AudioSource的PlayOnAwake没关导致场景加载时音频就在播放等到按钮触发时再调用Play()实际上是在播放一个已经播放了一半的音频。解决方法是把所有AudioSource的PlayOnAwake关掉在需要播放的时候手动调用Play()。另外如果音频文件本身有前导静音也会导致延迟感。可以用音频编辑工具把前导静音剪掉或者在代码里用PlayScheduled()精确控制播放时间。还有一个问题是音频不同步——粒子爆发了但音效还没响或者音效响了但粒子还没爆发。这个问题的根源是协程里的等待时间和实际效果时长不匹配。我的解决方法是把粒子效果和音效的触发放在同一个方法里用同一个事件驱动而不是分别用不同的等待时间控制。// 错误做法分别控制 StartCoroutine(PlayParticlesAfterDelay(0.5f)); StartCoroutine(PlaySoundAfterDelay(0.6f)); // 正确做法统一控制 private void PlayWishEffects() { particleSystem.Play(); audioSource.Play(); }4.3 文案随机抽取的边界情况随机抽取的边界情况主要有两个空列表和权重全为零。空列表的情况是文案库还没配置任何文案这时候调用GetRandomWish()会返回null导致后续代码报空引用异常。解决方法是在方法开头加一个判空检查if (wishList null || wishList.Count 0) { Debug.LogWarning(文案库为空返回默认文案); return defaultWish; }权重全为零的情况是配置失误所有文案的权重都设成了0导致总权重为0随机数生成会出错。解决方法是在计算总权重后加一个检查if (totalWeight 0) { Debug.LogError(总权重为0请检查文案权重配置); return wishList[0]; }避坑技巧在ScriptableObject的OnValidate()方法里加一个权重检查如果发现所有权重都是0就在Inspector面板里弹出警告。这样可以在编辑阶段就发现问题不用等到运行时才报错。4.4 常见问题速查表问题现象可能原因排查方法解决方案粒子显示为粉色方块材质Shader不兼容检查Renderer的Material换成Particles/Standard Unlit粒子被UI遮挡Sorting Layer设置错误检查粒子和UI的Sorting Layer给粒子单独设Sorting Layer音效播放延迟PlayOnAwake未关闭检查AudioSource设置关闭PlayOnAwake手动Play音效与粒子不同步等待时间不匹配用秒表掐实际效果时长统一事件驱动不用分别等待文案抽取报空引用文案库为空检查ScriptableObject配置加判空检查返回默认文案连续抽到同一条文案没有去重机制检查随机逻辑加去重缓冲队列稀有文案抽不到权重设置太极端检查权重配置调整权重比例普通60/稀有30/史诗10打包后粒子效果丢失材质未包含在构建中检查Build Settings把材质加入Always Included Shaders4.5 一些踩过的坑和独家经验第一个坑是粒子系统的Simulation Space。默认是Local意思是粒子会跟着父物体移动。如果祈愿区域是一个会移动的物体粒子也会跟着移动效果会很奇怪。我一开始没注意这个祈愿区域的物体有一个轻微的上下浮动动画结果粒子也跟着上下浮动看起来像在“抖”。后来把Simulation Space改成World就好了。第二个坑是UI的Canvas Scaler。如果Canvas Scaler的UI Scale Mode设成了Constant Pixel Size在不同分辨率的屏幕上UI大小会不一致。我一开始用的就是这个模式在编辑器里看着好好的打包到手机上发现按钮小得点不到。后来改成Scale With Screen SizeReference Resolution设成1920x1080Match设成0.5这样在不同分辨率下UI会自动缩放适配性就好多了。第三个坑是音频的压缩格式。Unity默认的音频压缩格式是Vorbis对于短音效来说解码延迟比较高。我把短音效按钮声、祈愿声的压缩格式改成了PCM未压缩虽然文件大了一点但播放延迟几乎为零。背景音还是用Vorbis因为背景音对延迟不敏感用Vorbis可以减小包体。第四个坑是协程的嵌套。我一开始在WishSequence()协程里又启动了其他协程导致协程嵌套层级太深调试的时候很难追踪执行顺序。后来改成用一个协程串行执行所有步骤每个步骤用yield return new WaitForSeconds()分隔逻辑就清晰多了。如果确实需要并行执行用事件系统代替协程嵌套。第五个坑是PlayerPrefs的存储时机。我一开始在每次祈愿后都调用PlayerPrefs.Save()结果发现频繁保存会导致卡顿。后来改成在OnApplicationPause()和OnApplicationQuit()里统一保存平时只改内存里的数据不立即写磁盘。这样既保证了数据不丢失又避免了频繁IO导致的性能问题。这个项目后续还可以这样扩展加一个“祈愿历史”界面用ScrollView展示玩家之前的祈愿记录加一个“文案收集”系统玩家抽到的文案会解锁到图鉴里加一个“每日祈愿”限制每天只能祈愿一次增加仪式感。这些扩展都不需要改动核心架构只需要在现有的事件系统上挂新的监听模块就行。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑