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

如何让Unity游戏角色生成时不与方块发生穿插?

解决角色传送至方块上方的碰撞穿插问题

核心思路

通过检测目标传送位置的碰撞情况,自动调整角色位置至方块顶部的安全区域,避免角色底部陷入方块后上移的问题。具体步骤:

  1. 获取角色碰撞体的尺寸信息,计算角色中心到地面的高度偏移量。
  2. 对点击位置进行双重检测:先向下射线判断下方是否有地面方块,再检测目标位置是否存在碰撞。
  3. 根据检测结果调整传送位置,确保角色与地面无穿插。

修改后的完整代码

public class PlayerSpawner : MonoBehaviour
{
    public GameObject player;
    public Vector2 groundChecker;
    public float castDistance;
    public LayerMask groundLayer;
    private Collider2D playerCollider;
    private float playerHalfHeight; // 角色中心到底部的距离

    void Start()
    {
        // 自动获取角色碰撞体组件
        playerCollider = player.GetComponent<Collider2D>();
        if (playerCollider != null)
        {
            // 计算角色碰撞体的半高(中心到边缘的垂直距离)
            playerHalfHeight = playerCollider.bounds.extents.y;
        }
        else
        {
            Debug.LogError("角色对象缺少Collider2D组件,请添加!");
        }
    }

    void Update()
    {
        if(Input.GetMouseButtonDown(0) && IsGrounded())
        {
            Vector2 playerPosition = player.transform.position;
            Vector2 clickedPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            Vector2 distanceFromPlayer = clickedPosition - playerPosition;

            // 仅处理传送范围内的点击
            if (distanceFromPlayer.magnitude < 3)
            {
                Vector2 targetPosition = clickedPosition;

                // 检测点击位置下方是否有地面方块
                RaycastHit2D groundHit = Physics2D.Raycast(targetPosition, Vector2.down, playerHalfHeight + 0.1f, groundLayer);
                if (groundHit.collider != null)
                {
                    // 将角色放在方块顶部,刚好避免碰撞
                    targetPosition.y = groundHit.point.y + playerHalfHeight;
                }
                else
                {
                    // 若目标位置本身与地面碰撞,逐步向上偏移至安全位置
                    while (Physics2D.OverlapBox(targetPosition, playerCollider.bounds.size, 0, groundLayer))
                    {
                        targetPosition += Vector2.up * 0.1f;
                        // 防止无限循环,设置最大偏移上限
                        if ((targetPosition.y - clickedPosition.y) > 2)
                        {
                            Debug.LogWarning("无法找到安全传送位置,已停止偏移");
                            break;
                        }
                    }
                }

                player.transform.position = targetPosition;
            }
        }
    }

    private void OnDrawGizmos()
    {
        Vector2 playerPosition = player.transform.position;
        // 绘制传送范围的可视化边界
        Gizmos.DrawWireSphere(playerPosition, 3);
        // 绘制角色碰撞体的边界,方便调试
        if (playerCollider != null)
        {
            Gizmos.DrawWireCube(player.transform.position, playerCollider.bounds.size);
        }
    }

    public bool IsGrounded()
    {
        return Physics2D.BoxCast(transform.position, groundChecker, 0, -transform.up, castDistance, groundLayer);
    }
}

关键修改说明

  • 自动获取碰撞体信息:在Start方法中自动获取角色的Collider2D,无需手动拖拽赋值,同时计算角色中心到地面的半高,确保偏移距离准确。
  • 双重碰撞检测:
    1. 向下射线检测:快速判断点击位置下方是否有地面方块,直接将角色放置在方块顶部的安全位置。
    2. 重叠区域检测:处理点击位置本身在方块内部的情况,逐步向上偏移直到找到无碰撞区域,并添加偏移上限防止无限循环。
  • 调试可视化:修改OnDrawGizmos,绘制传送范围和角色碰撞体边界,方便调试时观察位置是否正确。

游戏场景截图

角色传送至方块上方的碰撞问题截图

内容的提问来源于stack exchange,提问作者Seyit Şahin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 08:17:41