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

unity 有打击感的图片,怎么做动画,可以表现出良好的打击效果

 完整实现脚本:

using UnityEngine;
using UnityEngine.UI;
using System.Collections;[RequireComponent(typeof(Image))]
public class HitEffectController : MonoBehaviour
{[Header("基础设置")]public float hitDuration = 0.5f; // 打击效果总时长[Header("缩放效果")]public float maxScale = 1.3f; // 最大缩放值public float scaleInDuration = 0.05f; // 缩放进入时间public float scaleOutDuration = 0.2f; // 缩放恢复时间public AnimationCurve scaleCurve = AnimationCurve.EaseInOut(0, 0, 1, 1);[Header("震动效果")]public float shakeIntensity = 10f; // 震动强度public float shakeFrequency = 25f; // 震动频率public AnimationCurve shakeCurve = AnimationCurve.EaseInOut(0, 0, 1, 1);[Header("闪光效果")]public Color flashColor = Color.white; // 闪光颜色public float flashDuration = 0.1f; // 闪光持续时间public float flashIntensity = 5f; // 闪光强度[Header("运动模糊")]public bool useMotionBlur = true;public float stretchAmount = 0.3f; // 拉伸量public float stretchDuration = 0.08f; // 拉伸持续时间[Header("粒子效果")]public ParticleSystem hitParticles;public int particleCount = 15; // 粒子数量[Header("时间效果")]public float freezeDuration = 0.05f; // 时间冻结时长private Image targetImage;private RectTransform rectTransform;private Vector3 originalScale;private Color originalColor;private Material originalMaterial;private Coroutine currentEffect;void Awake(){targetImage = GetComponent<Image>();rectTransform = GetComponent<RectTransform>();originalScale = rectTransform.localScale;originalColor = targetImage.color;originalMaterial = targetImage.material;}// 触发打击效果public void TriggerHitEffect(){if (currentEffect != null) StopCoroutine(currentEffect);currentEffect = StartCoroutine(HitEffectRoutine());}private IEnumerator HitEffectRoutine(){// 1. 时间冻结(强调击中瞬间)Time.timeScale = 0f;yield return new WaitForSecondsRealtime(freezeDuration);Time.timeScale = 1f;// 2. 初始缩放(表现冲击)float scaleTimer = 0f;while (scaleTimer < scaleInDuration){scaleTimer += Time.deltaTime;float t = scaleCurve.Evaluate(scaleTimer / scaleInDuration);float scale = Mathf.Lerp(1f, maxScale, t);rectTransform.localScale = originalScale * scale;yield return null;}// 3. 同时触发闪光和粒子效果StartCoroutine(FlashEffect());EmitParticles();// 4. 运动模糊(可选)if (useMotionBlur){StartCoroutine(StretchEffect());}// 5. 缩放恢复+震动效果float shakeTimer = 0f;Vector3 originalPosition = rectTransform.localPosition;while (shakeTimer < hitDuration){shakeTimer += Time.deltaTime;// 缩放恢复if (shakeTimer < scaleOutDuration){float scaleT = scaleCurve.Evaluate(shakeTimer / scaleOutDuration);float scale = Mathf.Lerp(maxScale, 1f, scaleT);rectTransform.localScale = originalScale * scale;}// 震动效果float shakeT = shakeCurve.Evaluate(shakeTimer / hitDuration);float shakeMagnitude = shakeIntensity * (1f - shakeT);float offsetX = Mathf.Sin(Time.time * shakeFrequency) * shakeMagnitude;float offsetY = Mathf.Cos(Time.time * shakeFrequency) * shakeMagnitude;rectTransform.localPosition = originalPosition + new Vector3(offsetX, offsetY, 0);yield return null;}// 恢复原始状态rectTransform.localScale = originalScale;rectTransform.localPosition = originalPosition;}// 闪光效果协程private IEnumerator FlashEffect(){// 创建临时材质实现闪光Material flashMaterial = new Material(Shader.Find("UI/Unlit/Transparent"));targetImage.material = flashMaterial;float timer = 0f;while (timer < flashDuration){timer += Time.deltaTime;float t = Mathf.Clamp01(timer / flashDuration);// 强度曲线:快速达到峰值然后衰减float intensity = flashIntensity * Mathf.Sin(t * Mathf.PI);// 混合原始颜色和闪光颜色Color blendedColor = Color.Lerp(originalColor, flashColor, intensity);flashMaterial.color = blendedColor;yield return null;}// 恢复原始材质targetImage.material = originalMaterial;Destroy(flashMaterial);}// 运动模糊拉伸效果private IEnumerator StretchEffect(){Vector3 originalScale = rectTransform.localScale;Vector3 stretchedScale = new Vector3(originalScale.x * (1f + stretchAmount),originalScale.y * (1f - stretchAmount * 0.5f),originalScale.z);float timer = 0f;while (timer < stretchDuration){timer += Time.deltaTime;float t = timer / stretchDuration;// 使用缓动函数实现快速拉伸然后恢复float stretchT = Mathf.Sin(t * Mathf.PI * 0.5f);rectTransform.localScale = Vector3.Lerp(originalScale, stretchedScale, stretchT);yield return null;}rectTransform.localScale = originalScale;}// 发射粒子private void EmitParticles(){if (hitParticles != null){// 在图片位置发射粒子hitParticles.transform.position = rectTransform.position;hitParticles.Emit(particleCount);}}
}

 


 

参数优化建议
缩放效果
csharp
maxScale = 1.2f - 1.5f; // 根据图片大小调整
scaleInDuration = 0.03f - 0.07f; // 快速冲击
scaleOutDuration = 0.15f - 0.3f; // 缓慢恢复
震动效果
csharp
shakeIntensity = 5f - 20f; // 小图片用小值,大图片用大值
shakeFrequency = 20f - 30f; // 高频震动更真实
闪光效果
csharp
// 根据图片主色调选择对比色
flashColor = ComplementaryColor(originalColor); 
flashIntensity = 3f - 8f; // 强度根据场景亮度调整

高级效果增强技巧

1. 材质与着色器效果

冲击波着色器:

// 简化的冲击波着色器
Shader "Custom/HitWave"
{Properties{_MainTex ("Texture", 2D) = "white" {}_WaveCenter ("Wave Center", Vector) = (0.5, 0.5, 0, 0)_WaveAmount ("Wave Amount", Range(0, 1)) = 0_WaveIntensity ("Wave Intensity", Float) = 10}SubShader{// 着色器代码...float2 waveOffset = (distance(i.uv, _WaveCenter.xy) * _WaveIntensity * _WaveAmount;float2 distortedUV = i.uv + waveOffset;fixed4 col = tex2D(_MainTex, distortedUV);// 增加边缘发光col.rgb += _WaveAmount * _WaveIntensity * 0.1 * (1 - smoothstep(0, 0.2, distance(i.uv, _WaveCenter.xy)));}
}

2. 屏幕空间效果

全局屏幕震动:

public class ScreenShake : MonoBehaviour
{public float duration = 0.5f;public float intensity = 0.1f;private Vector3 originalPos;private float currentShakeTime;void Start(){originalPos = transform.localPosition;}public void Shake(){currentShakeTime = duration;}void Update(){if (currentShakeTime > 0){float percent = currentShakeTime / duration;Vector2 offset = UnityEngine.Random.insideUnitCircle * intensity * percent;transform.localPosition = originalPos + new Vector3(offset.x, offset.y, 0);currentShakeTime -= Time.deltaTime;}else{transform.localPosition = originalPos;}}
}

  3. 音效同步

[Header("音效设置")]
public AudioClip hitSound;
public AudioClip impactSound;
public float soundDelay = 0.02f;private AudioSource audioSource;void Start()
{audioSource = gameObject.AddComponent<AudioSource>();
}private IEnumerator PlayHitSounds()
{audioSource.PlayOneShot(hitSound);yield return new WaitForSeconds(soundDelay);audioSource.PlayOneShot(impactSound);
}

 

 4. 物理模拟碎片

[Header("碎片效果")]
public GameObject fragmentPrefab;
public int fragmentCount = 10;
public float explosionForce = 300f;private void CreateFragments()
{for (int i = 0; i < fragmentCount; i++){GameObject fragment = Instantiate(fragmentPrefab, transform.position, Quaternion.identity);Rigidbody2D rb = fragment.GetComponent<Rigidbody2D>();if (rb != null){Vector2 direction = Random.insideUnitCircle.normalized;rb.AddForce(direction * explosionForce);rb.AddTorque(Random.Range(-100f, 100f));}Destroy(fragment, Random.Range(0.5f, 1.5f));}
}

 参数组合方案

参数组合方案
轻度打击效果
csharp
hitDuration = 0.3f;
maxScale = 1.15f;
shakeIntensity = 5f;
flashIntensity = 3f;
freezeDuration = 0.02f;
中度打击效果
csharp
hitDuration = 0.5f;
maxScale = 1.25f;
shakeIntensity = 10f;
flashIntensity = 5f;
freezeDuration = 0.05f;
useMotionBlur = true;
重度打击效果
csharp
hitDuration = 0.7f;
maxScale = 1.4f;
shakeIntensity = 15f;
flashIntensity = 8f;
freezeDuration = 0.08f;
useMotionBlur = true;
// 启用碎片效果
CreateFragments();

 


 其他:

性能优化建议
对象池管理:csharp
public class FragmentPool : MonoBehaviour
{public GameObject fragmentPrefab;public int poolSize = 20;private Queue<GameObject> fragmentPool = new Queue<GameObject>();void Start(){for (int i = 0; i < poolSize; i++){GameObject fragment = Instantiate(fragmentPrefab);fragment.SetActive(false);fragmentPool.Enqueue(fragment);}}public GameObject GetFragment(){if (fragmentPool.Count > 0){GameObject fragment = fragmentPool.Dequeue();fragment.SetActive(true);return fragment;}return Instantiate(fragmentPrefab);}public void ReturnFragment(GameObject fragment){fragment.SetActive(false);fragmentPool.Enqueue(fragment);}
}
材质共享:csharp
private static Material flashMaterial;void Awake()
{if (flashMaterial == null){flashMaterial = new Material(Shader.Find("UI/Unlit/Transparent"));}// 使用共享材质
}
按需启用:csharp
void OnEnable()
{// 初始化
}void OnDisable()
{// 清理资源
}
使用示例
csharp
// 在UI按钮上添加点击效果
public class HitButton : MonoBehaviour
{public HitEffectController hitEffect;void Start(){Button button = GetComponent<Button>();button.onClick.AddListener(OnButtonClick);}void OnButtonClick(){hitEffect.TriggerHitEffect();}
}// 在游戏角色受击时
public class CharacterHealth : MonoBehaviour
{public HitEffectController hitEffect;public ScreenShake screenShake;public void TakeDamage(){hitEffect.TriggerHitEffect();screenShake.Shake();// 其他伤害处理...}
}
效果组合策略
轻重攻击区分:轻攻击:缩放+轻微震动重攻击:缩放+震动+闪光+屏幕震动+粒子元素类型反馈:物理攻击:灰色粒子+屏幕震动火焰攻击:红色闪光+火焰粒子冰霜攻击:蓝色闪光+冰晶粒子命中部位差异:头部命中:加强屏幕震动身体命中:标准效果四肢命中:减弱效果总结
要创建具有强烈打击感的图片动画,关键在于多种效果的组合运用:时间控制:通过时间冻结强调击中瞬间空间变形:缩放、拉伸和震动表现物理冲击视觉特效:闪光和粒子增加细节反馈辅助效果:屏幕震动和音效增强沉浸感参数优化:根据不同场景调整效果强度通过调整上述脚本中的参数和组合不同的效果模块,可以为各种游戏场景创建出令人满意的打击效果。记得在实际应用中根据游戏风格和性能要求进行适当调整。

 


 转载于:

http://www.dtcms.com/a/273748.html

相关文章:

  • STM32串口通信(寄存器与hal库实现)
  • 2025年7月11日学习笔记一周归纳——模式识别与机器学习
  • 高校智慧教室物联网系统设计与实现
  • 《磁力下载工具实测:资源搜索+高速下载一站式解决方案》
  • 串行数据检测器,检测到011,Y输出1,否则为0.
  • JavaScript加强篇——第五章 DOM节点(加强)与BOM
  • 网安系列【18】之SpringBoot漏洞
  • React Three Fiber 实现 3D 模型点击高亮交互的核心技巧
  • 小架构step系列11:单元测试引入
  • Rocky Linux上使用NVM安装Node.js 18
  • 老系统改造增加初始化,自动化数据源配置(tomcat+jsp+springmvc)
  • 大数据时代UI前端的用户体验设计新思维:以数据为驱动的情感化设计
  • golang -gorm 增删改查操作,事务操作
  • 分布式推客系统全栈开发指南:SpringCloud+Neo4j+Redis实战解析
  • Neo4j启动
  • 从一到无穷大 #47:浅谈对象存储加速
  • 基于vscode的go环境安装简介
  • 企业级LLM知识库:构建智能知识管理平台,赋能业务增长
  • 降本增效!上云真香!
  • 如何批量旋转视频90度?
  • 基于Selenium和FFmpeg的全平台短视频自动化发布系统
  • 通过命名空间引用了 Application 类,php不会自动包含路径文件吗?
  • Vue 中的属性绑定:从基础到实战进阶
  • docker0网卡没有ip一步解决
  • Kotlin基础
  • leetcode 3169. 无需开会的工作日 中等
  • 格式规范公文处理助手:一键排版 标题 / 正文 / 页码一键调,Word 脚本自定义
  • Apache Cloudberry 向量化实践(三)重塑表达式构建路径:Gandiva 优化实战
  • 如何将公式图片转换为公式格式到wps/word里面
  • 【java17】使用 Word 模板导出带替换符、动态表格和二维码的文档