Unity中抓取防穿模效果

1.抓取的不会穿透其它带碰撞的模型。
2.碰撞会受质量影响,质量大的容易撞开质量小的,质量小的不容易撞开质量大的。
3.可以开启连续碰撞检测选项避免一些高速运动等特殊情况的穿透,但也会增加一定性能开销。

// An highlighted block
/*----------------------------------------------------------------
// 文件名:GrabFollow.cs
// 功能描述:自定义抓取(代码直接挂在要被抓取的物体上,注意删除默认的抓取脚本)
// 
// 创建标识:辛羊华 2024/5/25 10:17:22
// 
// 修改标识:
// 修改描述:
//
//----------------------------------------------------------------*/
using UnityEngine;
using UnityEngine.EventSystems;
using zSpace.Core.Input;

public class GrabFollow : ZPointerInteractable, IBeginDragHandler, IDragHandler, IEndDragHandler
{
    [Header("使用连续检测碰撞")]
    public bool ContinuousDetection;    //可防止快速运动穿透模型,但会增加性能开销

    private const float m_MaxVelocityChange = 10f;
    private const float m_VelocityMagic = 6000f;
    private const float m_AngularVelocityMagic = 50f;
    private const float m_MaxAngularVelocityChange = 20f;

    /// <summary>
    /// 笔
    /// </summary>
    private ZStylus m_ZStylus;
        /// <summary>
    /// 该物体的刚体
    /// </summary>
    private Rigidbody m_Rigi;
    /// <summary>
    /// 抓取前的自带刚体
    /// </summary>
    private Rigidbody m_OriRigi;
    /// <summary>
    /// 抓取连接物
    /// </summary>
    private GameObject m_GrabHandle;
    /// <summary>
    /// 跟随目标位置
    /// </summary>
    private Transform m_Target;

    void Start()
    {
        m_ZStylus = GameObject.FindObjectOfType<ZStylus>();
    }

    public void OnBeginDrag(PointerEventData eventData)
    {
        //获取自身刚体或添加一个刚体
        m_OriRigi = GetComponent<Rigidbody>();
        if (m_OriRigi == null)
        {
            m_Rigi = gameObject.AddComponent<Rigidbody>();
        }
        else
        {
            m_Rigi = m_OriRigi;
        }

        if (ContinuousDetection)
        {
            m_Rigi.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;
        }
                //生成一个关节跟随物体
        m_GrabHandle = new GameObject("GrabHandle");
        m_GrabHandle.transform.position = this.transform.position;
        m_GrabHandle.transform.rotation = this.transform.rotation;
        m_GrabHandle.transform.SetParent(m_ZStylus.Visualization.transform);
        m_Target = m_GrabHandle.transform;
    }
  
    public void OnEndDrag(PointerEventData eventData)
    {
        //还原抓取前状态
        m_Target = null;
        Destroy(m_GrabHandle);
        if (m_OriRigi == null) Destroy(m_Rigi);  //删除添加的刚体
    }

    private void FixedUpdate()
    {
        if (m_Target)
        {
            UpdateFollow();
        }
    }
  
    private void UpdateFollow()
    {
        Vector3 velocityTarget; //目标速度
        Vector3 angularTarget;  //目标角速度
        bool success = GetUpdatedVelocities(out velocityTarget, out angularTarget);
        if (success)
        {
            m_Rigi.velocity = Vector3.MoveTowards(m_Rigi.velocity, velocityTarget, m_MaxVelocityChange);
            m_Rigi.angularVelocity = Vector3.MoveTowards(m_Rigi.angularVelocity, angularTarget, m_MaxAngularVelocityChange);
        }
    }

    /// <summary>
    /// 获取目标速度
    /// </summary>
    /// <param name="velocityTarget"></param>
    /// <param name="angularTarget"></param>
    /// <returns></returns>
    protected bool GetUpdatedVelocities(out Vector3 velocityTarget, out Vector3 angularTarget)
    {
        bool realNumbers = false;
        //速度
        Vector3 positionDelta = (m_Target.position - transform.position);
        velocityTarget = (positionDelta * m_VelocityMagic * Time.deltaTime);

              if (float.IsNaN(velocityTarget.x) == false && float.IsInfinity(velocityTarget.x) == false)
        {
            velocityTarget /= 10;

            realNumbers = true;
        }
        else
        {
            velocityTarget = Vector3.zero;
        }

              //角速度
        Quaternion rotationDelta = m_Target.rotation * Quaternion.Inverse(transform.rotation);

        float angle;
        Vector3 axis;
        rotationDelta.ToAngleAxis(out angle, out axis);

        if (angle > 180) angle -= 360;

        if (angle != 0 && float.IsNaN(axis.x) == false && float.IsInfinity(axis.x) == false)
        {
            angularTarget = angle * axis * m_AngularVelocityMagic * Time.deltaTime;

            angularTarget /= 10;

            realNumbers &= true;
        }
        else
        {
            angularTarget = Vector3.zero;
        }

        return realNumbers;
    }
}
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值