Unity 2D玩家向鼠标方向有限半径避障传送实现求助
2D玩家鼠标方向传送实现方案
核心逻辑
- 转换鼠标屏幕坐标到2D世界空间
- 计算并限制传送目标点在设定半径内
- 通过圆形区域检测判断目标点是否为空闲空间(避开障碍物)
- 检测通过则完成传送
完整代码
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 _
相关产品推荐
相关产品推荐

