如何实现玩家靠近火焰对象时仅单次触发后退动画?
玩家靠近火焰仅触发一次后退动画修复
现有8个标记为"Spreaded Fire"的对象,需求是当玩家靠近任意一个该类对象时,仅播放一次"Walk Backward"动画。
当前代码存在逻辑缺陷:动画会被多次触发;即使多个火焰对象在检测范围内,也无法保证仅触发一次动画。
原问题代码
using System.Collections; using System.Collections.Generic; using System.Linq; using TMPro; using UnityEngine; using UnityStandardAssets.Characters.ThirdPerson; public class SpreadedFireDistanceCheck : MonoBehaviour { public Transform player; public List<GameObject> spreadedFires = new List<GameObject> (); private Animator anim; private bool doOnce = true; void Start() { spreadedFires = GameObject.FindGameObjectsWithTag("Spreaded Fire").ToList(); anim = player.GetComponent<Animator>(); } private void Update() { foreach(GameObject spreadedFire in spreadedFires) { if(Vector3.Distance(player.transform.position, spreadedFire.transform.position) < 5f && doOnce) { anim.Play("Walk Backward"); doOnce = false; } else { doOnce = true; } } } }
问题根源
原代码的遍历逻辑存在致命缺陷:
- 每遍历一个火焰对象就修改
doOnce的值,当第一个火焰触发动画并将doOnce设为false后,下一个不在范围内的火焰会立即把doOnce改回true - 导致后续每一帧Update中,只要有火焰在范围内,动画就会被反复触发
修复后的代码
using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityStandardAssets.Characters.ThirdPerson; public class SpreadedFireDistanceCheck : MonoBehaviour { public Transform player; public List<GameObject> spreadedFires = new List<GameObject>(); private Animator anim; private bool hasPlayedBackwardAnim = false; void Start() { spreadedFires = GameObject.FindGameObjectsWithTag("Spreaded Fire").ToList(); anim = player.GetComponent<Animator>(); } private void Update() { // 一次性判断是否有任意火焰在玩家5米范围内 bool isNearAnyFire = spreadedFires.Any(fire => Vector3.Distance(player.position, fire.transform.position) < 5f); // 仅当进入火焰范围且未播放过动画时触发一次 if (isNearAnyFire && !hasPlayedBackwardAnim) { anim.Play("Walk Backward"); hasPlayedBackwardAnim = true; } // 离开火焰范围后重置状态,下次靠近可再次触发 else if (!isNearAnyFire && hasPlayedBackwardAnim) { hasPlayedBackwardAnim = false; } } }
关键修改点
- 语义化变量命名:将
doOnce改为hasPlayedBackwardAnim,状态含义更清晰 - 批量判断逻辑:使用
Any()方法一次性检测所有火焰,避免逐个遍历修改状态 - 状态控制逻辑优化:仅在「进入范围且未触发过动画」时播放一次;离开范围后重置状态,保证下次靠近仍能触发
- 清理冗余引用:移除了未使用的
TMPro命名空间
内容的提问来源于stack exchange,提问作者Daniel Lip
相关产品推荐
相关产品推荐

