EX-GAS扩展开发指南:自定义GameplayCue和AbilityTask的高级技巧
EX-GAS扩展开发指南自定义GameplayCue和AbilityTask的高级技巧【免费下载链接】gameplay-ability-system-for-unityGameplay-Ability-System For Unity项目地址: https://gitcode.com/gh_mirrors/ga/gameplay-ability-system-for-unityEX-GASGameplay Ability System是Unity游戏开发中强大的技能系统框架为开发者提供了完整的游戏能力管理解决方案。本文将深入探讨EX-GAS中两个核心扩展点GameplayCue和AbilityTask帮助开发者掌握自定义这些组件的高级技巧提升游戏表现力和交互体验。什么是GameplayCue为什么需要自定义GameplayCue是EX-GAS中的游戏提示系统负责处理游戏效果的可视化表现如特效、音效、动画等。它遵循不干涉游戏数值的原则专注于表现层逻辑。GameplayCue的核心原则不干涉数值体系Cue不应该修改游戏属性或Buff数值不影响核心玩法在即时战斗游戏中Cue不应该影响角色位移等核心战斗逻辑专注表现层主要负责视觉效果、音效播放等表现层功能自定义GameplayCue的基本结构每个GameplayCue都由两部分组成GameplayCue类数据配置类继承自GameplayCueT负责编辑器中的参数配置GameplayCueSpec类运行时逻辑类继承自GameplayCueSpec负责实际执行逻辑创建自定义瞬时Cue示例让我们创建一个播放自定义音效的GameplayCueInstant// 自定义音效Cue数据类 [CreateAssetMenu(fileName CustomSoundCue, menuName GAS/Cue/CustomSoundCue)] public class CustomSoundCue : GameplayCueInstant { [SerializeField] private AudioClip soundClip; [SerializeField] private float volume 1.0f; [SerializeField] private Vector3 positionOffset Vector3.zero; public override GameplayCueInstantSpec CreateSpec(GameplayCueParameters parameters) { return new CustomSoundCueSpec(this, parameters); } } // 自定义音效Cue规格类 public class CustomSoundCueSpec : GameplayCueInstantSpecCustomSoundCue { public CustomSoundCueSpec(CustomSoundCue cue, GameplayCueParameters parameters) : base(cue, parameters) { } public override void Trigger() { // 获取拥有者位置 Vector3 position Owner.transform.position cue.positionOffset; // 播放音效 AudioSource.PlayClipAtPoint(cue.soundClip, position, cue.volume); // 可以添加更多逻辑如粒子效果、屏幕震动等 Debug.Log($播放音效: {cue.soundClip.name} 于 {Owner.name}); } }创建自定义持续Cue示例持续Cue适合需要长时间运行的效果如光环特效、持续音效等// 自定义光环Cue数据类 [CreateAssetMenu(fileName AuraCue, menuName GAS/Cue/AuraCue)] public class AuraCue : GameplayCueDurational { [SerializeField] private GameObject auraPrefab; [SerializeField] private float auraScale 1.0f; [SerializeField] private Color auraColor Color.white; public override GameplayCueDurationalSpec CreateSpec(GameplayCueParameters parameters) { return new AuraCueSpec(this, parameters); } } // 自定义光环Cue规格类 public class AuraCueSpec : GameplayCueDurationalSpecAuraCue { private GameObject auraInstance; private Material auraMaterial; public AuraCueSpec(AuraCue cue, GameplayCueParameters parameters) : base(cue, parameters) { } public override void OnAdd() { // 创建光环实例 auraInstance GameObject.Instantiate(cue.auraPrefab, Owner.transform); auraInstance.transform.localScale Vector3.one * cue.auraScale; // 设置光环颜色 auraMaterial auraInstance.GetComponentRenderer()?.material; if (auraMaterial ! null) { auraMaterial.color cue.auraColor; } } public override void OnRemove() { // 销毁光环实例 if (auraInstance ! null) { GameObject.Destroy(auraInstance); } } public override void OnGameplayEffectActivate() { // 激活光环 if (auraInstance ! null) { auraInstance.SetActive(true); } } public override void OnGameplayEffectDeactivate() { // 隐藏光环 if (auraInstance ! null) { auraInstance.SetActive(false); } } public override void OnTick() { // 每帧更新逻辑 if (auraInstance ! null) { // 可以添加旋转、缩放动画等 auraInstance.transform.Rotate(0, 30 * Time.deltaTime, 0); } } }GameplayCue在编辑器中的配置界面AbilityTask技能逻辑的可视化编排AbilityTask是EX-GAS中用于实现技能逻辑的可视化工具特别适合用于TimelineAbility中。它允许开发者将复杂的技能逻辑分解为可重用的任务单元。AbilityTask的类型EX-GAS提供了两种主要的AbilityTask类型InstantAbilityTask即时任务在特定时间点执行一次OngoingAbilityTask持续任务在时间范围内持续执行创建自定义即时任务示例让我们创建一个发射子弹的即时任务// 发射子弹任务数据类 [System.Serializable] public class ShootProjectileTaskData : AbilityTaskData { public GameObject projectilePrefab; public float projectileSpeed 10f; public float damage 10f; public Vector3 spawnOffset Vector3.forward; } // 发射子弹任务类 public class ShootProjectileTask : InstantAbilityTask { private ShootProjectileTaskData data; public override void Init(AbilitySpec spec) { base.Init(spec); // 从Spec中获取任务数据 data spec.GetTaskDataShootProjectileTaskData(); } public override void OnExecute() { if (data.projectilePrefab null) return; // 计算发射位置和方向 Vector3 spawnPosition Spec.Owner.transform.position Spec.Owner.transform.TransformDirection(data.spawnOffset); Quaternion spawnRotation Spec.Owner.transform.rotation; // 实例化子弹 GameObject projectile GameObject.Instantiate( data.projectilePrefab, spawnPosition, spawnRotation ); // 设置子弹属性 ProjectileController controller projectile.GetComponentProjectileController(); if (controller ! null) { controller.damage data.damage; controller.speed data.projectileSpeed; controller.owner Spec.Owner; } // 添加力或速度 Rigidbody rb projectile.GetComponentRigidbody(); if (rb ! null) { rb.velocity Spec.Owner.transform.forward * data.projectileSpeed; } } }创建自定义持续任务示例持续任务适合处理需要随时间变化的效果如持续伤害区域// 持续伤害区域任务数据类 [System.Serializable] public class DamageAreaTaskData : AbilityTaskData { public GameObject areaPrefab; public float radius 5f; public float damagePerSecond 5f; public float duration 3f; } // 持续伤害区域任务类 public class DamageAreaTask : OngoingAbilityTask { private DamageAreaTaskData data; private GameObject areaInstance; private float elapsedTime; public override void Init(AbilitySpec spec) { base.Init(spec); data spec.GetTaskDataDamageAreaTaskData(); } public override void OnStart(int startFrame) { // 创建伤害区域 areaInstance GameObject.Instantiate(data.areaPrefab, Spec.Owner.transform.position, Quaternion.identity); areaInstance.transform.localScale Vector3.one * data.radius * 2; elapsedTime 0f; } public override void OnEnd(int endFrame) { // 销毁伤害区域 if (areaInstance ! null) { GameObject.Destroy(areaInstance); } } public override void OnTick(int frameIndex, int startFrame, int endFrame) { if (areaInstance null) return; // 更新计时 elapsedTime Time.deltaTime; // 每帧检测范围内的敌人并造成伤害 Collider[] colliders Physics.OverlapSphere(areaInstance.transform.position, data.radius); foreach (var collider in colliders) { AbilitySystemComponent target collider.GetComponentAbilitySystemComponent(); if (target ! null target ! Spec.Owner) { // 应用伤害效果 ApplyDamageToTarget(target); } } // 检查持续时间 if (elapsedTime data.duration) { // 任务结束 OnEnd(endFrame); } } private void ApplyDamageToTarget(AbilitySystemComponent target) { // 创建伤害GameplayEffect GameplayEffect damageEffect CreateDamageEffect(); target.ApplyGameplayEffectToSelf(damageEffect); } }TimelineAbility编辑器中的任务轨道配置高级技巧GameplayCue与AbilityTask的协同工作在实际开发中GameplayCue和AbilityTask经常需要协同工作。下面是一个综合示例展示如何将它们结合使用示例连击技能系统// 连击技能数据类 [CreateAssetMenu(fileName ComboAbility, menuName GAS/Ability/ComboAbility)] public class ComboAbilityAsset : AbilityAsset { public int maxComboCount 3; public float comboResetTime 2f; public GameObject[] comboEffects; // 不同连击段数的特效 public AudioClip[] comboSounds; // 不同连击段数的音效 public override Type AbilityType() { return typeof(ComboAbility); } } // 连击技能类 public class ComboAbility : AbstractAbilityComboAbilityAsset { private int currentCombo 0; private float lastAttackTime 0f; public ComboAbility(ComboAbilityAsset abilityAsset) : base(abilityAsset) { } public override AbilitySpec CreateSpec(AbilitySystemComponent owner) { return new ComboAbilitySpec(this, owner); } } // 连击技能规格类 public class ComboAbilitySpec : AbilitySpec { private ComboAbilityAsset comboData; private int currentCombo 0; private float lastAttackTime 0f; public ComboAbilitySpec(ComboAbility ability, AbilitySystemComponent owner) : base(ability, owner) { comboData (ComboAbilityAsset)ability.DataReference; } public override void ActivateAbility(params object[] args) { // 检查连击重置 if (Time.time - lastAttackTime comboData.comboResetTime) { currentCombo 0; } // 增加连击计数 currentCombo (currentCombo % comboData.maxComboCount) 1; lastAttackTime Time.time; // 执行连击攻击 ExecuteComboAttack(currentCombo); // 播放连击特效和音效 PlayComboEffects(currentCombo); // 更新UI显示 UpdateComboUI(currentCombo); } private void ExecuteComboAttack(int comboLevel) { // 根据连击等级执行不同的攻击逻辑 switch (comboLevel) { case 1: // 第一段攻击 ExecuteFirstAttack(); break; case 2: // 第二段攻击 ExecuteSecondAttack(); break; case 3: // 第三段攻击 ExecuteThirdAttack(); break; } } private void PlayComboEffects(int comboLevel) { // 使用GameplayCue播放特效 if (comboLevel - 1 comboData.comboEffects.Length) { GameObject effectPrefab comboData.comboEffects[comboLevel - 1]; if (effectPrefab ! null) { // 创建自定义特效Cue ComboEffectCue cue ScriptableObject.CreateInstanceComboEffectCue(); cue.effectPrefab effectPrefab; cue.comboLevel comboLevel; // 应用Cue cue.ApplyFrom(this); } } // 播放音效 if (comboLevel - 1 comboData.comboSounds.Length) { AudioClip sound comboData.comboSounds[comboLevel - 1]; if (sound ! null) { // 使用自定义音效Cue CustomSoundCue soundCue ScriptableObject.CreateInstanceCustomSoundCue(); soundCue.soundClip sound; soundCue.volume 1.0f; soundCue.ApplyFrom(this); } } } }性能优化与最佳实践1. GameplayCue性能优化// 使用对象池优化频繁创建的Cue public class PooledVFXCue : GameplayCueDurational { [SerializeField] private string poolKey vfx_pool; [SerializeField] private int poolSize 10; public override GameplayCueDurationalSpec CreateSpec(GameplayCueParameters parameters) { return new PooledVFXCueSpec(this, parameters); } } public class PooledVFXCueSpec : GameplayCueDurationalSpecPooledVFXCue { private GameObject vfxInstance; public PooledVFXCueSpec(PooledVFXCue cue, GameplayCueParameters parameters) : base(cue, parameters) { } public override void OnAdd() { // 从对象池获取实例 vfxInstance ObjectPoolManager.Instance.GetFromPool(cue.poolKey); if (vfxInstance null) { // 池为空时创建新实例 vfxInstance GameObject.Instantiate(cue.VfxPrefab); ObjectPoolManager.Instance.AddToPool(cue.poolKey, vfxInstance); } vfxInstance.transform.position Owner.transform.position; vfxInstance.SetActive(true); } public override void OnRemove() { // 归还到对象池 if (vfxInstance ! null) { ObjectPoolManager.Instance.ReturnToPool(cue.poolKey, vfxInstance); vfxInstance null; } } }2. AbilityTask的编辑器集成为了让自定义的AbilityTask在TimelineAbility编辑器中可用需要创建对应的Inspector#if UNITY_EDITOR using UnityEditor; using GAS.Editor; // 发射子弹任务的Inspector [CustomEditor(typeof(ShootProjectileTaskData))] public class ShootProjectileTaskInspector : InstantTaskInspectorShootProjectileTask { public override void OnInspectorGUI() { base.OnInspectorGUI(); ShootProjectileTaskData data (ShootProjectileTaskData)target; EditorGUILayout.Space(); EditorGUILayout.LabelField(子弹设置, EditorStyles.boldLabel); data.projectilePrefab (GameObject)EditorGUILayout.ObjectField( 子弹预制体, data.projectilePrefab, typeof(GameObject), false ); data.projectileSpeed EditorGUILayout.FloatField(子弹速度, data.projectileSpeed); data.damage EditorGUILayout.FloatField(伤害值, data.damage); data.spawnOffset EditorGUILayout.Vector3Field(生成偏移, data.spawnOffset); if (GUI.changed) { EditorUtility.SetDirty(data); } } } #endif3. 参数验证与错误处理public class SafeGameplayCue : GameplayCueInstant { [SerializeField] private GameObject effectPrefab; [SerializeField] private bool useFallback true; [SerializeField] private GameObject fallbackPrefab; public override GameplayCueInstantSpec CreateSpec(GameplayCueParameters parameters) { // 参数验证 if (!ValidateParameters()) { Debug.LogError($SafeGameplayCue参数验证失败: {name}); return null; } return new SafeGameplayCueSpec(this, parameters); } private bool ValidateParameters() { if (effectPrefab null) { if (useFallback fallbackPrefab ! null) { effectPrefab fallbackPrefab; return true; } return false; } return true; } }调试与测试技巧1. 使用GAS运行时监视器GAS运行时监视器是调试GameplayCue和AbilityTask的强大工具可以实时查看当前激活的Ability属性值变化正在运行的GameplayEffect标签状态2. 自定义调试信息public class DebugGameplayCue : GameplayCueInstant { [SerializeField] private string debugMessage; [SerializeField] private Color debugColor Color.white; public override GameplayCueInstantSpec CreateSpec(GameplayCueParameters parameters) { return new DebugGameplayCueSpec(this, parameters); } } public class DebugGameplayCueSpec : GameplayCueInstantSpecDebugGameplayCue { public DebugGameplayCueSpec(DebugGameplayCue cue, GameplayCueParameters parameters) : base(cue, parameters) { } public override void Trigger() { // 在场景中显示调试信息 Debug.Log($color#{ColorUtility.ToHtmlStringRGB(cue.debugColor)}{cue.debugMessage}/color); // 在拥有者位置显示文字 if (Owner ! null) { ShowFloatingText(Owner.transform.position, cue.debugMessage, cue.debugColor); } } private void ShowFloatingText(Vector3 position, string text, Color color) { // 实现浮动文字显示逻辑 // 可以使用TextMeshPro、UGUI或其他方式 } }总结与建议自定义GameplayCue和AbilityTask是EX-GAS扩展开发的核心技能。通过掌握这些技巧你可以创建丰富的视觉效果通过自定义GameplayCue实现独特的游戏表现构建复杂的技能逻辑利用AbilityTask实现可重用的技能组件提高开发效率通过可视化编辑减少代码量增强系统灵活性创建可配置的游戏效果系统最佳实践总结保持Cue的纯粹性GameplayCue只负责表现不干涉游戏逻辑合理使用AbilityTask将复杂技能分解为可重用的任务单元注意性能优化使用对象池、缓存等技巧优化频繁创建的对象完善的错误处理验证参数提供备用方案充分利用编辑器创建友好的Inspector界面提高策划配置效率通过本文介绍的高级技巧你可以充分发挥EX-GAS的潜力创建出更加丰富、灵活的游戏能力系统。记住良好的扩展设计不仅能提升游戏质量还能显著提高开发效率更多详细信息和API参考请查看项目中的官方文档和Ability文档。【免费下载链接】gameplay-ability-system-for-unityGameplay-Ability-System For Unity项目地址: https://gitcode.com/gh_mirrors/ga/gameplay-ability-system-for-unity创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

AI Agent的“骨架”之争:四种Harness设计哲学深度解构

AI Agent的“骨架”之争:四种Harness设计哲学深度解构

1. 引言 2025年,AI Agent 已从实验室概念走向生产级应用。然而,当开发者真正着手构建一个 Agent 系统时,最先面临的不是模型选型,而是一个更底层的问题:Agent 的“骨架”该怎么搭? 这个“骨架”就是 Agent …

2026/7/19 16:19:26阅读更多 →
Plotly区间滑块交互设计:GPT-4驱动的直觉化可视化实战

Plotly区间滑块交互设计:GPT-4驱动的直觉化可视化实战

1. 项目概述:这不是炫技,是把交互可视化从“能用”推向“直觉化”的一次实战 你有没有过这种体验:花两小时调好一个Plotly图表,加了下拉菜单、悬停提示、图例开关,自以为很专业——结果同事点开第一眼就问:…

2026/7/19 16:19:26阅读更多 →
AI模型功能完整度评估体系首次解密,覆盖37项原子能力指标,附开源评分工具链下载

AI模型功能完整度评估体系首次解密,覆盖37项原子能力指标,附开源评分工具链下载

更多请点击: https://intelliparadigm.com 第一章:AI模型功能完整度评估体系首次解密 传统AI模型评估长期聚焦于准确率、F1值等单一维度指标,忽视了模型在真实业务场景中必须具备的多维能力支撑。本章首次公开一套可落地、可量化、可扩展的A…

2026/7/19 16:19:26阅读更多 →
ngx_output_chain_get_buf

ngx_output_chain_get_buf

1 定义 ngx_output_chain_get_buf 函数 定义在 src/core/ngx_output_chain.cstatic ngx_int_t ngx_output_chain_get_buf(ngx_output_chain_ctx_t *ctx, off_t bsize) {size_t size;ngx_buf_t *b, *in;ngx_uint_t recycled;in ctx->in->buf;size ctx->buf…

2026/7/20 0:15:05阅读更多 →
互联网大厂常见Java面试题及答案汇总(2026持续更新)

互联网大厂常见Java面试题及答案汇总(2026持续更新)

金九银十即将来袭,又是一个跳槽的好季节,准备跳槽的同学都摩拳擦掌准备大面好几场,今天为大家准备了互联网面试必备的 1 到 5 年 Java 面试者都需要掌握的面试题,分别 JVM,并发编程,MySQL,Tomca…

2026/7/20 0:15:05阅读更多 →
python数据可视化技巧的100个练习 -- 31. 类别数据的点图

python数据可视化技巧的100个练习 -- 31. 类别数据的点图

重要性★★★☆☆ 难度★★☆☆☆ 你是一家零售公司的数据分析师。你的经理要求你可视化最近产品发布的客户满意度评级分布。评级是分类的,范围从“非常不满意”到“非常满意”。创建一个点图以显示每个评级类别的频率。使用 Python 进行数据处理和可视化。在代码中生成输入…

2026/7/20 0:13:05阅读更多 →
智能体走进物理世界,千里科技携舱驾协同成果亮相WAIC 2026

智能体走进物理世界,千里科技携舱驾协同成果亮相WAIC 2026

在2026世界人工智能大会(WAIC 2026)举办期间,千里科技董事长、阶跃星辰董事长印奇作为特邀嘉宾出席大会开幕式并在大会主论坛(上午场)发表主题演讲《当智能体进入物理世界》。在印奇看来,"智能体"…

2026/7/20 0:13:05阅读更多 →
商汤大装置发布“技术-生态-商业”闭环布局,共启“国产AI基础设施规模化商用元年”

商汤大装置发布“技术-生态-商业”闭环布局,共启“国产AI基础设施规模化商用元年”

7月18日,在WAIC 2026商汤科技 “基座大模型架构创新与生态合作论坛”上,商汤科技联合创始人、大装置事业群总裁杨帆发表《智变共生——加速AI基础设施持续升级》主题演讲,系统呈现了商汤大装置国产AI基础设施“技术-生态-商业”闭环布局&…

2026/7/20 0:13:05阅读更多 →
2026郑州美发学校避坑指南:拆解5种教学方式,谁在“流水线”谁在“真传技”?

2026郑州美发学校避坑指南:拆解5种教学方式,谁在“流水线”谁在“真传技”?

2026年想在郑州学美发,很多零基础学员最先搜索的问题就是:郑州美发学校哪家好?这个问题没有一个只看学校名字就能得出的答案。因为不同学校的课程方向、学习周期、教学方式和适合人群并不一样。有的更适合零基础,有的偏向发型师进修,还有的只做某一项短期技术培训。对于完全没…

2026/7/20 0:11:05阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/20 0:50:54阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/20 0:50:54阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/20 0:50:54阅读更多 →
2026 WAIC:努比亚二代“豆包手机”NaviX Ultra亮相,智能体验全面升级!

2026 WAIC:努比亚二代“豆包手机”NaviX Ultra亮相,智能体验全面升级!

7月18日智东西消息,在2026 WAIC期间,努比亚联合字节豆包打造的二代“豆包手机”努比亚NaviX Ultra首次亮相,相比一代有诸多升级。智能体手机理念中兴通讯终端事业部总裁、努比亚总裁倪飞表示,智能体手机要从人操作手机变为手机帮人…

2026/7/20 0:01:04阅读更多 →
努比亚NaviX Ultra亮相WAIC,智能体手机能否让用户生活更简单?

努比亚NaviX Ultra亮相WAIC,智能体手机能否让用户生活更简单?

努比亚NaviX Ultra:外观与功能双升级在2026 WAIC期间,首次亮相的努比亚NaviX Ultra吸引了众多目光。它是努比亚联合字节豆包打造的二代“豆包手机”,与一代努比亚M153相比,外观设计变化较大。其机身背部搭载横向排布的大尺寸影像模…

2026/7/20 0:01:04阅读更多 →
C# 将逗号分割的字符串转换为long,并添加到List<long>

C# 将逗号分割的字符串转换为long,并添加到List<long>

目录 方法1:使用Split和Convert.ToInt64 方法2:使用LINQ的Select和ToList 方法3:使用TryParse进行异常安全转换(推荐) 如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天…

2026/7/20 0:01:04阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/19 22:50:49阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/19 14:50:26阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/19 18:50:36阅读更多 →