Unity 2D角色碰撞时仍播放行走动画,射线检测异常问题求助
问题分析
你遇到的两个问题根源在于射线检测的准确性不足,以及未处理持续碰撞场景:
- 上下移动碰墙动画不停止:当前射线从角色中心发射,可能无法精准命中Tilemap碰撞器;同时代码依赖
tag == "wall"判断,但Tilemap碰撞器可能未添加该标签,导致检测失效。 - 连续Tile仅触发一次碰撞:单次射线检测无法覆盖持续碰撞状态,当角色已与Tile重叠时,射线可能无法检测到后续碰撞。
解决方案
1. 修正射线检测逻辑
- 将射线起点从角色中心移至角色碰撞器边缘,确保检测方向的射线从角色外部出发,避免错过Tilemap碰撞器。
- 移除不必要的
tag判断,直接通过LayerMask过滤墙体层,减少额外依赖。
2. 处理持续碰撞
通过OnCollisionStay2D监听持续碰撞事件,当角色持续接触墙体时,强制停止动画并重置移动输入。
3. 优化移动逻辑
碰到墙时重置movement向量,避免角色在碰撞状态下仍尝试移动。
修改后的完整代码
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerScript : MonoBehaviour { public float moveSpeed; private Animator ani; private bool isMoving; private Vector2 lastMove; private Rigidbody2D body; private Vector2 movement; private LayerMask wallLayer = 1 << 6; private BoxCollider2D collider; void Start() { body = GetComponent<Rigidbody2D>(); ani = GetComponent<Animator>(); collider = GetComponent<BoxCollider2D>(); movement = Vector2.zero; isMoving = false; } void Update() { isMoving = false; movement = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical")); if (movement.magnitude > 0) { // 计算射线起点:从角色碰撞器边缘向移动方向偏移 Vector2 rayOrigin = body.position + collider.offset; rayOrigin += (Vector2)collider.bounds.extents * movement.normalized; // 发射短射线检测前方墙体 RaycastHit2D ray = Physics2D.Raycast(rayOrigin, movement, 0.1f, wallLayer); if (!ray) { isMoving = true; lastMove = movement; } else { // 碰到墙时重置移动向量 movement = Vector2.zero; } } ani.SetFloat("MoveX", movement.x); ani.SetFloat("MoveY", movement.y); ani.SetFloat("LastX", lastMove.x); ani.SetFloat("LastY", lastMove.y); ani.SetBool("IsMoving", isMoving); } void FixedUpdate() { body.MovePosition(body.position + movement * moveSpeed * Time.deltaTime); } // 监听持续碰撞事件 private void OnCollisionStay2D(Collision2D other) { // 检查碰撞对象是否属于墙体层 if (((1 << other.gameObject.layer) & wallLayer) != 0) { isMoving = false; movement = Vector2.zero; ani.SetBool("IsMoving", false); } } }
额外注意事项
- 确保Tilemap的
Tilemap Collider 2D组件勾选Used By Composite,并添加Composite Collider 2D组件,让连续Tile形成连续碰撞区域,避免检测缝隙。 - 确认Tilemap所在Layer确实为第6层,与代码中的
wallLayer = 1 << 6对应。
内容的提问来源于stack exchange,提问作者lev
相关产品推荐
相关产品推荐

