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

Unity中绑定HingeJoint2D的旋转物体碰撞后收缩实现问题

问题描述

我有一个绑定在HingeJoint2D(黑色铰链关节)上可绕其旋转的橙色物体。当检测到与其他物体发生碰撞时(红色点位置),需要将该物体从铰链到碰撞点的部分收缩,同时要保持物体与铰链的连接以及自身宽度。

[示意图:橙色物体通过黑色铰链关节连接,红色点为碰撞位置]
[层级结构示意图:橙色物体作为子物体嵌套在父物体下]

现有尝试代码

碰撞检测逻辑

void OnCollisionEnter2D(Collision2D collision)
{
    GameObject obj = collision.gameObject;
    Vector3 endPos =collision.contacts[0].point;
    float scaleX = Vector3.Distance(new Vector3(startPos.x, 0, 0), new Vector3(endPos.x, 0, 0));
    float scaleY = Vector3.Distance(new Vector3(0, startPos.y, 0), new Vector3(0, endPos.y, 0));
    Vector3 newScale = new Vector3(scaleX,scaleY, 1);
    obj.transform.parent.transform.localScale = obj.transform.TransformPoint(newScale);
}

铰链位置初始化

startPos = GameObject.Find("hair").GetComponent<HingeJoint2D>().transform.position;

我将物体嵌套在父物体中并对父物体缩放,期望以此保持物体原位,但始终无法让物体保持正确位置和尺寸,请问该如何正确实现?


解决方案

核心问题在于你直接拆分XY轴计算距离,还错误用TransformPoint转换缩放值,导致缩放逻辑完全偏离预期。要实现从铰链到碰撞点收缩、维持宽度、不脱离铰链的效果,按以下步骤调整:

1. 先理清楚层级与轴心

保持父-子物体结构,但必须满足:

  • 父物体的轴心点完全对齐铰链关节的位置(父物体position等于铰链的startPos)
  • 橙色子物体的初始轴心在父物体的轴心处(也就是铰链位置),子物体的初始长度是从铰链到末端的原始长度

2. 修正碰撞时的缩放逻辑

不需要拆分XY轴计算,直接算铰链到碰撞点的直线距离,再基于这个距离调整父物体的长度方向缩放(宽度方向保持1不变):

// 提前缓存关键组件,避免运行时重复查找
private Transform parentTransform;
private Transform hingeTransform;
private float originalLength; // 橙色物体的初始长度

void Start()
{
    // 找到铰链关节的Transform
    hingeTransform = GameObject.Find("hair").GetComponent<HingeJoint2D>().transform;
    // 获取父物体Transform(假设脚本挂在橙色子物体上)
    parentTransform = transform.parent;
    // 记录物体初始长度:取Sprite的实际宽度(根据你的物体方向调整X/Y)
    originalLength = GetComponent<SpriteRenderer>().bounds.size.x;
    // 强制父物体位置与铰链对齐,确保缩放时锚点正确
    parentTransform.position = hingeTransform.position;
}

void OnCollisionEnter2D(Collision2D collision)
{
    // 获取碰撞点的世界坐标
    Vector3 collisionPos = collision.contacts[0].point;
    // 计算铰链到碰撞点的直线距离
    float collisionDistance = Vector3.Distance(hingeTransform.position, collisionPos);
    // 计算缩放比例:碰撞距离/初始长度(加最小值避免缩到0)
    float lengthScale = Mathf.Max(collisionDistance / originalLength, 0.01f);
    // 只缩放长度方向(这里假设长度沿X轴,若沿Y轴就改localScale.y),宽度保持1
    parentTransform.localScale = new Vector3(lengthScale, 1f, 1f);
}

3. 几个关键注意事项

  • 如果你的物体长度是沿Y轴延伸的,把代码里的localScale.x改成localScale.y即可
  • 可以直接把父物体设为铰链的子物体,这样父物体会自动继承铰链的旋转,不用额外处理旋转同步
  • 绝对不要用TransformPoint处理缩放值,localScale只需要传入比例系数,和坐标转换无关
  • 如果碰撞检测触发不稳定,可改用OnTriggerEnter2D,记得给碰撞体勾选「Is Trigger」

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 21:08:17