Unity 2D 关节(Joint 2D)的简单使用

2022年5月5日 1474点热度 1人点赞 2条评论

前言

Unity 物理引擎中有几种关节可以使用,主要用于实现类似绳索、弹簧、车轴等效果。

关节类型

2D 关节包括不同类型。请参阅每个关节参考页面以了解有关各自属性的详细信息:

  • 2D 距离关节 (Distance Joint 2D) - 连接由刚体物理组件控制的两个游戏对象,使这两个对象保持一定距离。
  • 2D 固定关节 (Fixed Joint 2D) - 将两个对象保持在相对于彼此的位置,确保对象始终以给定位置和角度偏移。例如,对象好像是采用刚性连接方式相连一样:对象不能彼此远离,不能相互靠近,也不能相对于彼此旋转。还可以使用此关节来创建刚度稍低的柔性连接。
  • 2D 摩擦关节 (Friction Joint 2D) - 将刚体物理组件控制的两个游戏对象之间的线速度和角速度降低到零(即:此关节使对象减速并停止)。例如,一个平台在旋转但抵抗该运动。
  • 2D 铰链关节 (Hinge Joint 2D) - 允许由刚体物理组件控制的游戏对象连接到空间中的一个点,使游戏对象可围绕该点旋转。例如,一把剪刀上的轴心。
  • 2D 相对关节 (Relative Joint 2D) - 允许由刚体物理组件控制的两个游戏对象基于彼此的位置来保持相对位置。使用此关节可将两个对象保持相互偏移。例如,在空间射击游戏中,玩家身后有额外的排炮。
  • 2D 滑动关节 (Slider Joint 2D) - 允许由刚体物理组件控制的游戏对象沿着空间中的一条线滑动(例如滑门)。
  • 2D 弹簧关节 (Spring Joint 2D) - 允许由刚体物理组件控制的两个游戏对象就像通过弹簧连接在一起一样。
  • 2D 目标关节 (Target Joint 2D) - 连接到指定目标,而不是像其他关节那样连接到另一个刚体对象。这是一种弹簧式关节,例如可将其用于拾取和移动处于重力作用下的对象。
  • 2D 车轮关节 (Wheel Joint 2D) - 模拟车轮和悬架。

关节的简单使用

在菜单栏Component -> Physics 2D 中可以看到关节组件,或者是在add Component 中搜索joint,需要注意的是后缀带有2D的就都是2D关节,如果没有则是3D关节。

以距离关节为例

image-20220502111819368

  1. Enable Collision 两个对象是否可以触发碰撞
  2. Connected Rigid Body 关节另一端的Rigidbody 对象,要使用关节,两个游戏对象都必须拥有Rigidbody 2D对象.
  3. Auto Configure connected Anchor 自动设置连接关节的锚点。
  4. Distance 距离,这个属性指定了第二个对象之后会自动设置
  5. Break Force 破坏关节需要的力度,infinity为无限大。如果为这个属性设置一个数值,那么当关节承受的力度超过这个数值,关节就会被破幻。

这只是部分属性,详细属性可以查阅官方文档。

关于设置锚点这里有一个小技巧,如果希望锚点与游戏对象的锚点一致,那么只需要将xy设置为0即可,如果是想自己定义锚点的偏倚,可以将鼠标悬浮在x上方,然后左键拖动鼠标可以移动锚点,这样移动之后可以在scene Window 中拖动锚点:Unity_joint_test1

然后这是使用距离关节的效果:

Unity_joint_test2

因为距离被固定了,然后对象受重力的影响就摆动起来了,这里的线条是用脚本绘制的,代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DisplayLine : MonoBehaviour
{
    public GameObject gameObject1;
    public GameObject gameObject2;
    private LineRenderer line;

    void Start()
    {
        //添加LineRenderer组件到物体上
        line = this.gameObject.AddComponent<LineRenderer>();

        //设置线渲染器的宽度
        line.startWidth = 0.05f;
        line.endWidth = 0.05f;

        //设置线条渲染器的顶点数
        line.positionCount = 2;
    }

    void Update()
    {
        if (gameObject1 != null && gameObject2 != null)
        {
            //分别设置两个顶点坐标
            line.SetPosition(0, gameObject1.transform.position);
            line.SetPosition(1, gameObject2.transform.position);
        }
    }
}

重力摩托车

我用关节实现了一个摩托车,下图为素材motorbike

将轮胎,减震,车身分割了一下,运行效果:

Unity_joint_test3

这里前减震在切图时忘了增加一下长度,导致往上弹时有点问题。

实现的具体方法其实就是讲这几个零件用关节连接起来。

分层

零件之间有遮挡效果,所以需要将不同的零件置于不同的渲染层,调节sort layer属性就可以了,两个轮子在最底层,然后是减震,最后是车身。

关节连接

image-20220502170243346

后减震红点部分是一个距离关节,然后两个黄色部分是两个弹簧关节,不过在前减震的黄色线条部分,还增加了一个滑动关节,固定前减震的位置。

车轮和减震之间都增加了车轮关节,这里需要注意车轮关节中可以调节两个锚点之间的弹性,因为这里使用单独的减震实现摩托车的动态效果,所以直接将值设置得很大。

车轮关节中有一个属性是Use Motor,勾选之后可以使用发动机,调节Motor speed属性就可以调节发动机的转速,在这个示例中也是使用这个属性移动摩托车的。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MotorBike : MonoBehaviour
{
    // Start is called before the first frame update
    public WheelJoint2D wheelLeft, wheelRight;
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        Vector3 pos = transform.position;
        pos.z = -10;
        camer.position = pos;
        JointMotor2D motor = wheelLeft.motor;
        motor.motorSpeed = -900 * Input.GetAxis("Horizontal");
        wheelLeft.motor = motor;
        wheelRight.motor = motor;

    }
}

参考资料:

大脸猫

这个人虽然很勤快,但什么也没有留下!

文章评论

  • 如花

    钟摆幅度越来越小,怎么解决呢?

    2022年11月16日
    • 大脸猫

      @如花 如果是图1类似的效果,应该是受重力的影响,所以钟摆会停,如果你不想让它停那么可以手动给精力施加力

      2022年11月16日