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

Unity:斜向移动问题——2D测试游戏玩家触屏边缘需停止而非瞬移

Hey there! Let’s work through this edge-stopping problem for your 2D diagonal player movement. I’ve dealt with exactly this kind of jitter and wonky behavior before, so here’s a solid solution that’ll get your player stopping smoothly at screen edges without the stutter.

Fixing Smooth Edge Stopping for 2D Diagonal Movement

The core issue with your current attempts is likely that you’re moving the player first and then trying to snap them back to the edge—this back-and-forth causes the jitter. Instead, we’ll calculate the player’s desired position before applying it, then clamp that position to stay within screen bounds.

Step 1: Calculate Screen Bounds (World Space)

First, we need to convert screen edges into world coordinates that work regardless of your camera’s size or aspect ratio. We’ll also account for the player’s collider so the entire sprite stays on screen, not just its pivot point.

private Vector2 _minBounds;
private Vector2 _maxBounds;

void Start()
{
    CalculateScreenBounds();
}

void CalculateScreenBounds()
{
    Camera mainCam = Camera.main;
    // Convert viewport corners (0-1 range) to world space
    Vector3 topRight = mainCam.ViewportToWorldPoint(new Vector3(1, 1, mainCam.transform.position.z));
    Vector3 bottomLeft = mainCam.ViewportToWorldPoint(new Vector3(0, 0, mainCam.transform.position.z));
    
    // Adjust bounds to fit the player's collider
    Collider2D playerCollider = GetComponent<Collider2D>();
    if (playerCollider != null)
    {
        Vector2 colliderHalfSize = playerCollider.bounds.extents;
        _minBounds = new Vector2(bottomLeft.x + colliderHalfSize.x, bottomLeft.y + colliderHalfSize.y);
        _maxBounds = new Vector2(topRight.x - colliderHalfSize.x, topRight.y - colliderHalfSize.y);
    }
    else
    {
        _minBounds = bottomLeft;
        _maxBounds = topRight;
    }
}

Step 2: Modify Movement Logic to Clamp Position

Now, update your movement code to calculate the desired position first, then restrict it to the bounds we set. We’ll also normalize the movement direction to ensure diagonal speed matches horizontal/vertical speed (a common oversight!).

For Non-Physics Movement (No Rigidbody2D)

public float moveSpeed = 5f;

void Update()
{
    // Get input for diagonal movement
    float horizontalInput = Input.GetAxis("Horizontal");
    float verticalInput = Input.GetAxis("Vertical");
    
    // Normalize direction to keep consistent speed across all axes
    Vector2 moveDirection = new Vector2(horizontalInput, verticalInput).normalized;
    Vector2 desiredPosition = transform.position + (moveDirection * moveSpeed * Time.deltaTime);
    
    // Clamp position to stay within screen bounds
    float clampedX = Mathf.Clamp(desiredPosition.x, _minBounds.x, _maxBounds.x);
    float clampedY = Mathf.Clamp(desiredPosition.y, _minBounds.y, _maxBounds.y);
    
    // Apply the clamped position
    transform.position = new Vector2(clampedX, clampedY);
}

For Physics-Based Movement (With Rigidbody2D)

If you’re using a Rigidbody2D for smoother physics integration, use rb.MovePosition() instead of directly setting transform.position:

private Rigidbody2D _rb;
public float moveSpeed = 5f;

void Awake()
{
    _rb = GetComponent<Rigidbody2D>();
    CalculateScreenBounds();
}

void FixedUpdate()
{
    float horizontalInput = Input.GetAxis("Horizontal");
    float verticalInput = Input.GetAxis("Vertical");
    
    Vector2 moveDirection = new Vector2(horizontalInput, verticalInput).normalized;
    Vector2 desiredPosition = _rb.position + (moveDirection * moveSpeed * Time.fixedDeltaTime);
    
    float clampedX = Mathf.Clamp(desiredPosition.x, _minBounds.x, _maxBounds.x);
    float clampedY = Mathf.Clamp(desiredPosition.y, _minBounds.y, _maxBounds.y);
    
    _rb.MovePosition(new Vector2(clampedX, clampedY));
}

Troubleshooting Tips

  • If your camera size or screen resolution changes during gameplay, call CalculateScreenBounds() again to update the bounds.
  • If you’re using Unity’s new Input System, replace Input.GetAxis with your input action references—the clamping logic stays identical.
  • Double-check that your player’s collider is properly sized; a mismatched collider can cause unexpected edge clipping.

This approach eliminates jitter by preventing the player from ever moving outside the screen bounds in the first place, resulting in clean, smooth edge stops.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 07:36:09