Unity 之 记录一个关于刚体穿透的问题

简介: 一个关于使用“杆” 接重力球,杆移动速度过快穿透过去的问题。

一,需求描述

需求:使得杆能够接住,依靠重力下落的球。
可是实现起来却和想象的不太一样,当杆移动速度快了就传过去了。
效果如下:
重力


二,遇到问题

看需求感觉还挺简单的。实现思路:几个球根据重力下落,一个“杆”跟随鼠标移动。步骤如下:

  • 创建几个球并 Rigidbody 组件,并勾选 useGravity 选项。
  • 搭建场景如下图:场景
  • 再创建一个Cube放大点(用来接住下落的球),也添加上Rigidbody 组件并添加 MouseMove 脚本:
using UnityEngine;

public class MouseMove : MonoBehaviour
{
    void Update()
    {
        if (Input.GetMouseButton(0))
        {
            // 根据鼠标位置 设置为 物体位置
            Vector3 screenPos = Camera.main.WorldToScreenPoint(this.transform.position);
            Vector3 mousePos = Input.mousePosition;
            mousePos.z = screenPos.z;
            Vector3 worldPos = Camera.main.ScreenToWorldPoint(mousePos);            
            // 控制物体移动
            transform.position = worldPos;
        }
    }
}

三,尝试解决

记得Rigidbody组件,可以通过Collision Detection属性来用于防止快速移动的对象穿过,这下面的检测方式都尝试了,也没有解决上述问题。
刚体组件

Unity 官方API:

Collision Detection 用于防止快速移动的对象穿过其他对象而不检测碰撞。
Discrete 对场景中的所有其他碰撞体使用离散碰撞检测。其他碰撞体在测试碰撞时会使用离散碰撞检测。用于正常碰撞(这是默认值)。
Continuous 对动态碰撞体(具有刚体)使用离散碰撞检测,并对静态碰撞体(没有刚体)使用基于扫掠的连续碰撞检测。设置为__连续动态 (Continuous Dynamic)__ 的刚体将在测试与该刚体的碰撞时使用连续碰撞检测。其他刚体将使用离散碰撞检测。用于__连续动态 (Continuous Dynamic)__ 检测需要碰撞的对象。(此属性对物理性能有很大影响,如果没有快速对象的碰撞问题,请将其保留为 Discrete 设置)
Continuous Dynamic 对设置为__连续 (Continuous)__ 和__连续动态 (Continuous Dynamic)__ 碰撞的游戏对象使用基于扫掠的连续碰撞检测。还将对静态碰撞体(没有刚体)使用连续碰撞检测。对于所有其他碰撞体,使用离散碰撞检测。用于快速移动的对象。
Continuous Speculative 对刚体和碰撞体使用推测性连续碰撞检测。这也是可以设置运动物体的唯一 CCD 模式。该方法通常比基于扫掠的连续碰撞检测的成本更低。

测试小结

  • 测试时也尝试了快速移动时的检测逻辑,在速度不是特别快的情况下,修改Collsion Detection选项调成Continues Dynamic是可以满足条件的,但是超过一定速度还是能穿透过去。
  • 记得在尝试过程中还看到过:调整ProjectSetting -> Time-> FixedTimestep的检测间隔进一步缩小。(例如0.003;提高物理系统的更新速度)==【测试也没成功】==
  • 若是发射子弹这种逻辑,可以使用射线检测的方式,在子弹发射的时候发射射线检测到的碰撞点进行逻辑判断处理。

四,实现需求

最后使用移动刚体的方式,来移动“杆”,测试结果如下:
刚体
修改后的代码:

using UnityEngine;

public class MouseMove : MonoBehaviour
{
    private Rigidbody _rigidbody;
    void Start()
    {
        _rigidbody = transform.GetComponent<Rigidbody>();
        // 取消重力
        _rigidbody.useGravity = false;
        // 设置为不再受物理引擎的影响
        _rigidbody.isKinematic = true;
    }

    void Update()
    {
        if (Input.GetMouseButton(0))
        {
            // 根据鼠标位置 设置为 物体位置
            Vector3 screenPos = Camera.main.WorldToScreenPoint(this.transform.position);
            Vector3 mousePos = Input.mousePosition;
            mousePos.z = screenPos.z;
            Vector3 worldPos = Camera.main.ScreenToWorldPoint(mousePos);
            
            // 控制物体移动
            //transform.position = worldPos;
            // 修改为刚体控制移动 --> 则不会被穿透了
            _rigidbody.MovePosition(worldPos);
        }
    }
}
相关文章
|
计算机视觉
Qt实用技巧:实现不规则窗口的鼠标消息穿透,包括穿透到桌面和穿透到父窗口
Qt实用技巧:实现不规则窗口的鼠标消息穿透,包括穿透到桌面和穿透到父窗口
|
3月前
|
容器
ThreeJs同一个场景多个相机的显示
这篇文章讲解了如何在Three.js中实现多相机功能,通过创建和布置多个相机及渲染器,从而能够在同一场景中从不同角度观察3D模型。
113 1
|
5月前
|
图形学
小功能⭐️解决Unity 3D UI遮挡穿透问题
小功能⭐️解决Unity 3D UI遮挡穿透问题
|
5月前
|
图形学
小功能⭐️Unity 如何判断物体是否在摄像机视野内或外
小功能⭐️Unity 如何判断物体是否在摄像机视野内或外
|
vr&ar 图形学
【Unity3D 灵巧小知识点】 ☀️ | 层级面板中的 ‘小手指‘ 作用: 在Scen中将该物体设置为不可选中状态
Unity 小科普 老规矩,先介绍一下 Unity 的科普小知识: Unity是 实时3D互动内容创作和运营平台 。 包括游戏开发、美术、建筑、汽车设计、影视在内的所有创作者,借助 Unity 将创意变成现实。 Unity 平台提供一整套完善的软件解决方案,可用于创作、运营和变现任何实时互动的2D和3D内容,支持平台包括手机、平板电脑、PC、游戏主机、增强现实和虚拟现实设备。
【Unity3D 灵巧小知识点】 ☀️ | 层级面板中的 ‘小手指‘ 作用: 在Scen中将该物体设置为不可选中状态
|
图形学 索引
Unity 之 查找游戏物体的几种方式解析
一篇小白也能看懂的查找游戏物体的方式解析 -- Unity 之 查找物体的几种方式。
1737 0
Unity 之 查找游戏物体的几种方式解析
|
前端开发 程序员
Threejs - 灯光?投影?? 有光的地方就会有影子
Threejs - 灯光?投影?? 有光的地方就会有影子
|
图形学 索引 存储
Unity 导出NavMesh (可行走区域判定) 数据给服务器使用
cp790621656 博客专家 Unity 导出NavMesh (可行走区域判定) 数据给服务器使用 发表于2016/9/26 18:15:11  1089人阅读 分类: Unity MMO 这个项目的客户端使用Unity 自带的 NavMesh 来做寻路。
Unity 导出NavMesh (可行走区域判定) 数据给服务器使用
unity3dUGUI空对象实现射线检测
using UnityEngine; using System.Collections; namespace UnityEngine.UI { public class Empty4Raycast : MaskableGraphic ...
2470 0
|
图形学
Unity 3D动态修改Shader状态,使物体透明等等
Unity动态改Shader状态透明 本文提供全流程,中文翻译。 Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例) Chinar...
4471 0