?完整實現腳本:
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();// 其他傷害處理...}
}
效果組合策略
輕重攻擊區分:輕攻擊:縮放+輕微震動重攻擊:縮放+震動+閃光+屏幕震動+粒子元素類型反饋:物理攻擊:灰色粒子+屏幕震動火焰攻擊:紅色閃光+火焰粒子冰霜攻擊:藍色閃光+冰晶粒子命中部位差異:頭部命中:加強屏幕震動身體命中:標準效果四肢命中:減弱效果總結
要創建具有強烈打擊感的圖片動畫,關鍵在于多種效果的組合運用:時間控制:通過時間凍結強調擊中瞬間空間變形:縮放、拉伸和震動表現物理沖擊視覺特效:閃光和粒子增加細節反饋輔助效果:屏幕震動和音效增強沉浸感參數優化:根據不同場景調整效果強度通過調整上述腳本中的參數和組合不同的效果模塊,可以為各種游戲場景創建出令人滿意的打擊效果。記得在實際應用中根據游戲風格和性能要求進行適當調整。
?