Unity中敌人攻击时相机不震动问题求助
问题:EnemyDamage的isDamaging为true时无法触发相机震动
需求:当EnemyDamage脚本中的isDamaging变量为true时,触发相机震动效果,但该功能未生效。打印isDamaging显示其值确实为true,但震动逻辑未执行。
相关脚本
震动脚本(gotHit)
using System.Collections; using UnityEngine; public class gotHit : MonoBehaviour { public bool start = false; public AnimationCurve curve; public float duration = 1f; private EnemyDamage enemyDamage; public Transform camera; private Coroutine shakeCoroutine; private void Awake() { enemyDamage = GameObject.FindWithTag("ucgen").GetComponent<EnemyDamage>(); } void Update() { if (start) { start = false; Debug.Log("start ile sarsılma başlatılıyor."); StartShaking(); } if (enemyDamage.isDamaging) { Debug.Log("enemyDamage.isDamaging ile sarsılma başlatılıyor."); StartShaking(); enemyDamage.isDamaging = false; } } void StartShaking() { if (shakeCoroutine != null) { StopCoroutine(shakeCoroutine); } shakeCoroutine = StartCoroutine(Shaking()); } IEnumerator Shaking() { Vector3 startPosition = camera.position; float elapsedTime = 0f; while (elapsedTime < duration) { elapsedTime += Time.deltaTime; float strength = curve.Evaluate(elapsedTime / duration); camera.position = startPosition + Random.insideUnitSphere * strength; yield return null; } camera.position = startPosition; } }
敌人伤害脚本(EnemyDamage)
using System.Collections; using UnityEngine; public class EnemyDamage : MonoBehaviour { public int enemyTriangleDamage = 2; private PlayerHealth playerHealth; public bool isDamaging = false; // 防止协程重复启动的标志 private void Awake() { GameObject player = GameObject.FindWithTag("Player"); if (player != null) { playerHealth = player.GetComponent<PlayerHealth>(); } } private void Update() { Debug.Log("isDamaging durumu: " + isDamaging); } private void OnCollisionStay2D(Collision2D collision2D) { if (!isDamaging && collision2D.gameObject.CompareTag("Player")) { StartCoroutine(Diee()); } } IEnumerator Diee() { isDamaging = true; yield return new WaitForSeconds(0.5f); if (playerHealth != null) { playerHealth.TakeDamage(enemyTriangleDamage); } isDamaging = false; } }
问题排查与修复方案
1. 核心逻辑冲突
当前gotHit脚本的Update方法中,检测到isDamaging为true时会直接将其设为false,这会干扰EnemyDamage自身的协程逻辑:EnemyDamage的Diee协程会在0.5秒后才将isDamaging设为false,但gotHit提前修改了该变量,可能导致震动触发逻辑异常,甚至重复触发Diee协程。
修复: 移除对enemyDamage.isDamaging的直接修改,改为监听状态变化(仅在isDamaging从false变为true时触发震动):
private bool lastIsDamaging = false; void Update() { if (start) { start = false; Debug.Log("通过start触发震动"); StartShaking(); } // 仅在isDamaging状态切换为true时触发震动 if (enemyDamage.isDamaging && !lastIsDamaging) { Debug.Log("通过enemyDamage.isDamaging触发震动"); StartShaking(); } lastIsDamaging = enemyDamage.isDamaging; }
2. 基础引用检查
- 确认
gotHit脚本的camera变量已在Inspector面板中正确赋值为主相机的Transform组件。 - 检查
GameObject.FindWithTag("ucgen")中的标签ucgen拼写正确,且挂载EnemyDamage的对象已添加该标签并处于激活状态。 - 验证
AnimationCurve曲线设置:确保曲线存在非零的强度值(例如从1线性降到0的曲线,保证震动有明显幅度)。
3. 相机位置修正
如果相机是某个父物体的子对象,使用世界空间的position可能导致震动异常,改为使用局部空间的localPosition:
IEnumerator Shaking() { Vector3 startPosition = camera.localPosition; float elapsedTime = 0f; while (elapsedTime < duration) { elapsedTime += Time.deltaTime; float strength = curve.Evaluate(elapsedTime / duration); camera.localPosition = startPosition + Random.insideUnitSphere * strength; yield return null; } camera.localPosition = startPosition; }
内容的提问来源于stack exchange,提问作者ybay
相关产品推荐
相关产品推荐

