Unity用代码实现关节的约束运动

Number of views 223

先看下面的图,我们有个游戏玩法,通过类似竹节的方式,把每一节的竹节连接起来,连接处会自动出现类似关节的小球。第一节的竹节会自动固定在特定的位置,但是也会自动生成一个关节小球,剩下的就是其中一个竹节的运动会带动其它竹节,但是要满足自然的约束关系,竹节可以无限生成,新生成的竹节会自动连接到当前最后一个竹节之后,并自动生成关节球。由于某些原因不能使用插件,不能使用内置的约束组件,因为代码要移植,竹节可以使用圆柱体替代,关节可以用球体替代

image1745567212099.png

3 Answers

这个是Cocos写的,自己转Unity吧,支持多关节(理论上可以无限关节),spider leg:

多关节铰链

为了实现这个需求,我们可以使用 Unity 的 RigidbodyHingeJoint 组件来模拟竹节和关节的行为。虽然你提到不能直接使用内置的约束组件,但我们可以手动编写代码来模拟这些行为。

以下是一个简单的示例代码,展示了如何实现这一功能:

  1. 创建一个竹节对象,每个竹节是一个带有 Rigidbody 和 Collider 的圆柱体。
  2. 创建一个关节对象,每个关节是一个带有 Rigidbody 和 Collider 的球体。
  3. 使用代码来管理竹节之间的连接和运动约束。

首先,创建一个竹节类 BambooSegment

using UnityEngine;

public class BambooSegment : MonoBehaviour
{
    public float mass = 1f;
    public Vector3 jointOffset = Vector3.up * 0.5f;

    private Rigidbody rb;
    private GameObject jointObject;
    private BambooSegment previousSegment;

    void Start()
    {
        // 初始化刚体
        rb = GetComponent<Rigidbody>();
        rb.mass = mass;
        rb.isKinematic = false;

        // 创建关节球体
        jointObject = new GameObject("Joint");
        jointObject.transform.parent = transform;
        jointObject.transform.localPosition = jointOffset;
        jointObject.AddComponent<Rigidbody>().isKinematic = true;
        jointObject.AddComponent<SphereCollider>();

        // 如果是第一个竹节,固定在原地
        if (previousSegment == null)
        {
            rb.isKinematic = true;
        }
    }

    public void SetPreviousSegment(BambooSegment segment)
    {
        previousSegment = segment;
    }

    public void UpdatePosition(Vector3 newPosition)
    {
        transform.position = newPosition;
        if (previousSegment != null)
        {
            Vector3 jointPosition = previousSegment.transform.position + previousSegment.jointOffset;
            jointObject.transform.position = jointPosition;
        }
    }
}

接下来,创建一个管理竹节生成和连接的脚本 BambooManager

using UnityEngine;

public class BambooManager : MonoBehaviour
{
    public GameObject bambooSegmentPrefab;
    public Transform fixedPoint;
    public int initialSegments = 1;
    public float segmentLength = 1f;

    private BambooSegment[] segments;

    void Start()
    {
        // 初始化第一个竹节
        GameObject firstSegmentObj = Instantiate(bambooSegmentPrefab, fixedPoint.position, Quaternion.identity);
        BambooSegment firstSegment = firstSegmentObj.GetComponent<BambooSegment>();
        firstSegment.UpdatePosition(fixedPoint.position);

        segments = new BambooSegment[initialSegments];
        segments[0] = firstSegment;

        // 初始化剩余的竹节
        for (int i = 1; i < initialSegments; i++)
        {
            CreateNewSegment();
        }
    }

    public void CreateNewSegment()
    {
        // 创建新的竹节
        GameObject newSegmentObj = Instantiate(bambooSegmentPrefab, Vector3.zero, Quaternion.identity);
        BambooSegment newSegment = newSegmentObj.GetComponent<BambooSegment>();

        // 设置前一个竹节
        newSegment.SetPreviousSegment(segments[segments.Length - 1]);

        // 更新位置
        Vector3 lastPosition = segments[segments.Length - 1].transform.position;
        newSegment.UpdatePosition(lastPosition + Vector3.right * segmentLength);

        // 添加到数组中
        BambooSegment[] newSegments = new BambooSegment[segments.Length + 1];
        System.Array.Copy(segments, newSegments, segments.Length);
        newSegments[newSegments.Length - 1] = newSegment;
        segments = newSegments;
    }
}

在这个示例中: - BambooSegment 类负责管理单个竹节的行为,包括其刚体、关节球体和与前一个竹节的连接。 - BambooManager 类负责管理竹节的生成和位置更新。

你可以根据需要调整这些脚本以适应你的具体需求。希望这能帮助你实现所需的竹节效果!

用Cocos creator3.x实现了版,支持多关节,蜘蛛腿,高性能的双关节方案:
Cocos多关节

ezgif4c5b34170f3e5d.gif

ezgif4f6c246d34de75.gif

ezgif2df04ce38d27d1.gif