You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 18:32:28