当前位置:   article > 正文

Unity使用ConfigurableJoint实现物理拖拽物体_unity configurable

unity configurable

我们如何在游戏中实现拖拽物体呢,如果仅仅是让拖拽坐标,可能没有物理效果,这里可以使用Joint来实现。

场景

首先我们在场景中放置道具。
在这里插入图片描述
如图,我们放置一个圆柱体Cylinder,一个Sphere球体,和地面。
圆柱体就是我们要拖动的物体,红色球体是我们点击的位置,白色的地面放置圆柱体掉下去。

我们在圆柱体上增加刚体,球体上也增加刚体,球体的Rig需要勾选运动学,因为Joint组件需要。

我们要实现鼠标点击圆柱体,拖拽,圆柱体跟随鼠标左右上下移动。

我们添加一个脚本CDrag挂在球体上。
在这里插入图片描述
变量HandRig就是球体的刚体。
变量Target就是圆柱体。

鼠标按下

在Update中,我们先写鼠标点击事件。我们要做的事情就是鼠标按下后,我们发射射线检测是否碰到圆柱体,然后把红色的球体移动过去,并且给圆柱体增加ConfigurableJoint,把他们两个联系起来,这样圆柱体就跟随球体了。代码如下:

	void Hand(float x, float y)
    {
        Vector3 at = new Vector3(x, y, myCamera.transform.position.z);
        Ray ray = myCamera.ScreenPointToRay(at);
        RaycastHit hit;
        Debug.DrawRay(ray.origin, ray.direction * 100f, Color.red, 1f);
        bool b = Physics.Raycast(ray, out hit, 100f, 1 << LayerMask.NameToLayer("Default"));
        if (b && hit.collider != null && hit.collider.name.Equals("Cylinder"))
        {
            HandRig.transform.position = hit.point;
            if (joint != null)
                Destroy(joint);
            joint = target.gameObject.AddComponent<ConfigurableJoint>();
            joint.connectedBody = HandRig;
            joint.xMotion = ConfigurableJointMotion.Locked;
            joint.yMotion = ConfigurableJointMotion.Locked;
            joint.zMotion = ConfigurableJointMotion.Locked;
            handupdis = Vector3.Distance(hit.point, myCamera.transform.position);
        }
    }
    
	void Update()
    {

        if (Input.GetMouseButtonDown(0))
        {
            Hand(Input.mousePosition.x,Input.mousePosition.y);
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

我们看到,在射线碰到圆柱体后,我们把红球改到了碰撞点位置,并且给target(圆柱体)增加了ConfigurableJoint,并且让他connectedBody到红球,并且设置x,y,z可以自由移动。最后handupdis是为了下面的移动准备的。

鼠标移动

然后我们再来处理移动
当我们移动的时候,我们只要移动球体,那么因为Joint被绑定到球体了,他也会跟着移动了。

		if (Input.GetMouseButton(0))
        {
            Move(Input.mousePosition);
        }
  • 1
  • 2
  • 3
  • 4
	private void Move(Vector3 pos)
    {
        pos.z = handupdis;
        Vector2 world = myCamera.ScreenToWorldPoint(pos);
        
        HandRig.transform.position = world;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

我们来看看效果。
请添加图片描述
有没有发下一个问题,红球点击圆柱体下面的时候,被拾取的点还是在顶部,我们需要计算锚点。

增加这行代码就舒服多了。

joint.anchor = joint.transform.InverseTransformPoint(hit.point);
  • 1

最后

我们把鼠标放开也一起写了,放上全部代码。

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

//UTF8支持
public class CDrag : MonoBehaviour
{
    [SerializeField] Rigidbody HandRig;
    [SerializeField] Transform target;
    Camera myCamera;
    ConfigurableJoint joint;

    float handupdis;
    Vector2 startpos;
    // Start is called before the first frame update
    void Start()
    {
        myCamera = Camera.main;
    }

    void Hand(float x, float y)
    {
        Vector3 at = new Vector3(x, y, myCamera.transform.position.z);
        Ray ray = myCamera.ScreenPointToRay(at);
        RaycastHit hit;
        Debug.DrawRay(ray.origin, ray.direction * 100f, Color.red, 1f);
        bool b = Physics.Raycast(ray, out hit, 100f, 1 << LayerMask.NameToLayer("Default"));
        if (b && hit.collider != null && hit.collider.name.Equals("Cylinder"))
        {
            HandRig.transform.position = hit.point;
            if (joint != null)
                Destroy(joint);
            joint = target.gameObject.AddComponent<ConfigurableJoint>();
            joint.connectedBody = HandRig;
            joint.xMotion = ConfigurableJointMotion.Locked;
            joint.yMotion = ConfigurableJointMotion.Locked;
            joint.zMotion = ConfigurableJointMotion.Locked;
            joint.anchor = joint.transform.InverseTransformPoint(hit.point);
            handupdis = Vector3.Distance(hit.point, myCamera.transform.position);
        }
    }

    private void Move(Vector3 pos)
    {
        pos.z = handupdis;
        Vector2 world = myCamera.ScreenToWorldPoint(pos);
        
        HandRig.transform.position = world;
    }
    void Update()
    {

        if (Input.GetMouseButtonDown(0))
        {
            Hand(Input.mousePosition.x,Input.mousePosition.y);
        }
        if (Input.GetMouseButton(0))
        {
            Move(Input.mousePosition);
        }
        if (Input.GetMouseButtonUp(0))
        {
            Destroy(joint);
        }
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67

最终效果如下:
请添加图片描述
最后,Joint家族里还可以使用其他的Joint来实现,例如SpringJoint,那就带有弹簧效果了,原理都是一样和一个刚体链接起来就可以了。

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号