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

Unity 2D玩家向鼠标方向有限半径避障传送实现求助

2D玩家鼠标方向传送实现方案

核心逻辑

  1. 转换鼠标屏幕坐标到2D世界空间
  2. 计算并限制传送目标点在设定半径内
  3. 通过圆形区域检测判断目标点是否为空闲空间(避开障碍物)
  4. 检测通过则完成传送

完整代码

using UnityEngine;

public class PlayerTeleport : MonoBehaviour
{
    [Header("传送参数")]
    [SerializeField] private float maxTeleportRadius = 5f; // 最大传送距离限制
    [SerializeField] private LayerMask obstacleLayers; // 不可传送的障碍物图层(如地板、墙壁)
    [SerializeField] private float freeSpaceCheckRadius = 0.2f; // 检测目标点是否空闲的半径(适配玩家碰撞体大小)

    private Camera _mainCamera;

    private void Awake()
    {
        _mainCamera = Camera.main;
    }

    private void Update()
    {
        // 按下空格键触发传送,可根据需求修改为鼠标右键或其他输入
        if (Input.GetKeyDown(KeyCode.Space))
        {
            ExecuteTeleport();
        }
    }

    private void ExecuteTeleport()
    {
        // 1. 转换鼠标位置到2D世界坐标
        Vector2 mouseWorldPosition = _mainCamera.ScreenToWorldPoint(Input.mousePosition);
        mouseWorldPosition = new Vector2(mouseWorldPosition.x, mouseWorldPosition.y);

        // 2. 计算玩家到鼠标点的方向与距离
        Vector2 directionToMouse = mouseWorldPosition - (Vector2)transform.position;
        float distanceToMouse = directionToMouse.magnitude;

        // 3. 确定最终传送目标点:超出半径则取半径极限点,否则用鼠标点
        Vector2 targetTeleportPos;
        if (distanceToMouse > maxTeleportRadius)
        {
            targetTeleportPos = (Vector2)transform.position + directionToMouse.normalized * maxTeleportRadius;
        }
        else
        {
            targetTeleportPos = mouseWorldPosition;
        }

        // 4. 检测目标点是否为空闲空间(无障碍物碰撞)
        bool isTargetPosFree = !Physics2D.OverlapCircle(targetTeleportPos, freeSpaceCheckRadius, obstacleLayers);

        // 5. 空闲则执行传送
        if (isTargetPosFree)
        {
            transform.position = targetTeleportPos;
        }
        else
        {
            Debug.Log("目标位置存在障碍物,无法传送");
        }
    }

    // Scene视图调试绘制:显示最大传送范围和目标检测点
    private void OnDrawGizmosSelected()
    {
        // 绘制最大传送半径
        Gizmos.color = Color.blue;
        Gizmos.DrawWireSphere(transform.position, maxTeleportRadius);

        // 绘制目标检测点
        if (_mainCamera != null)
        {
            Vector2 mouseWorldPos = _mainCamera.ScreenToWorldPoint(Input.mousePosition);
            Vector2 direction = mouseWorldPos - (Vector2)transform.position;
            float distance = direction.magnitude;
            Vector2 targetPos = distance > maxTeleportRadius ? (Vector2)transform.position + direction.normalized * maxTeleportRadius : mouseWorldPos;

            bool isFree = !Physics2D.OverlapCircle(targetPos, freeSpaceCheckRadius, obstacleLayers);
            Gizmos.color = isFree ? Color.green : Color.red;
            Gizmos.DrawWireSphere(targetPos, freeSpaceCheckRadius);
        }
    }
}

配置说明

  • 将脚本挂载到玩家GameObject上
  • 在Inspector面板配置参数:
    • maxTeleportRadius:设置允许的最大传送距离
    • obstacleLayers:选择包含地板、墙壁等不可传送障碍物的图层
    • freeSpaceCheckRadius:设置为玩家碰撞体的近似半径,确保检测区域匹配玩家实际占用空间
  • 确保玩家对象带有2D碰撞体(如CircleCollider2D),且未勾选Is Trigger(如需碰撞检测)
  • 触发按键可自行修改(比如改为Input.GetMouseButtonDown(1)实现右键传送)

内容的提问来源于stack exchange,提问作者PATRICK _

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 14:37:34