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

拖拽交互问题:如何固定被碰撞物体的位置?

解决Unity拖拽碰撞时保持物体位置且不穿模的问题

你的问题核心在于直接修改transform.position会绕过Unity的物理引擎,导致碰撞检测无法正常工作——当你冻结立方体位置时,物理系统没机会处理球体的"瞬移"移动,所以球直接穿过去了。下面给你两种靠谱的解决方案,按需选择:

方案一:改用物理驱动的拖拽(推荐)

修改你的拖拽脚本,用Rigidbody的MovePosition方法代替直接赋值transform.position,让物理引擎参与移动过程,这样碰撞检测会正常触发,同时冻结立方体位置就能让它保持不动。

修改后的拖拽脚本:

private bool dragging = false;
private float distance;
private Rigidbody rb;

void Awake() {
    rb = GetComponent<Rigidbody>();
    // 设置为运动学刚体,这样MovePosition会触发物理碰撞检测
    rb.isKinematic = true;
}

void OnMouseDown() {
    distance = Vector3.Distance(transform.position, Camera.main.transform.position);
    dragging = true;
}

void OnMouseUp() {
    dragging = false;
}

void Update() {
    if (dragging) {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        Vector3 rayPoint = ray.GetPoint(distance);
        // 用物理引擎处理移动,碰撞会正常生效
        rb.MovePosition(rayPoint);
    }
}

然后给立方体做以下设置:

  • 确保立方体有Collider组件(比如BoxCollider)且未禁用
  • 在立方体的Rigidbody组件中,勾选Constraints下的Freeze Position X/Y/Z

这样拖拽球体碰撞立方体时,球体会被立方体挡住(不会穿模),立方体也会稳稳保持在原位置。

方案二:给立方体添加位置锁定脚本(适配现有拖拽逻辑)

如果你不想修改现有的拖拽脚本,可以给立方体单独加一个脚本,在物理更新周期强制把它拉回初始位置,这样既保留碰撞检测,又能让它不被撞飞。

立方体的锁定脚本:

private Vector3 originalPosition;
private Rigidbody rb;

void Awake() {
    rb = GetComponent<Rigidbody>();
    // 记录初始位置
    originalPosition = transform.position;
}

void FixedUpdate() {
    // 物理帧更新时强制固定位置,避免被碰撞推动
    rb.MovePosition(originalPosition);
}

这种方式不需要冻结立方体的位置,球体直接改transform.position时,碰撞检测依然会触发,立方体也不会移动。缺点是如果你的场景有复杂物理交互,可能会有轻微的位置抖动,但大部分简单场景下完全够用。

关键注意点

  • 两个物体都必须有启用的Collider组件,否则碰撞检测根本不会触发
  • 如果用方案一,球体的Rigidbody必须设置为IsKinematic,否则MovePosition的行为会受重力、外力影响,拖拽体验不稳定

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:04:39