当前位置: 首页 > news >正文

Unity中刚体撞墙抖动的原因和本质

当我们制作角色移动的时候我们都知道使用设置位置的方法来移动一个带有刚体和碰撞体的物体,遇到碰撞体的时候就会抖动。

上网查找原因,都说是和物理系统冲突导致的,然后再也找不到其他线索。

这个说法,对,但它并不是最本质的原因。

我们都知道,fixedUpdate是固定间隔更新物理,在一帧中可能没有执行fxiedUpdate,也就是说没有更新物理。但是如果在一帧中执行了fixedUpdate,那么它一定是在Update之前更新的。

让我们考虑常见的移动代码:

    public float speed=3;

    private Vector3 moveVec;
    private void Update()
    {
        var horizontal = Input.GetAxis("Horizontal");
        var vertical = Input.GetAxis("Vertical");
        
        moveVec = new Vector3(horizontal,0,vertical);
        moveVec = Vector3.ClampMagnitude(moveVec, 1);
        
        Move(moveVec*speed,Time.deltaTime);
    }
    
    void Move(Vector3 vec, float deltaTime)
    {
        transform.position += vec * deltaTime;
    }

我们在移动的时候撞到墙时一定会抖动的。

        

让我们分析一下:

第1帧: 
fixedUpdate,啥也不干
update,把物体移动到墙内。
第2帧: 
fxiedUpdate,物理系统把物体移出到墙外
update,把物体再次移动到墙内。
第3帧: 
fxiedUpdate,物理系统把物体移出到墙外
update,把物体再次移动到墙内 
这样来看,相当于update覆盖了fixedUPdate的操作,不应该抖动啊?

我想了一个小时,chatgpt,deepseek各种都问过,都说我分析的没问题,但就是会抖动。

后来我终于想通了。

最本质的原因其实就是移动代码:transform.position += vec * deltaTime;

此代码等于transform.position = transform.position+vec * deltaTime;

也就是说他用的是当前位置来计算新的位置。

行为就变成了如下:

第1帧: 
fixedUpdate,啥也不干
update,把物体移动到墙内。
第2帧: 
fxiedUpdate,物理系统把物体移出到墙外位置A。
update,transform.position=位置A+vec * deltaTime;此时位置为B
第3帧: 
fxiedUpdate,物理系统把物体移出到墙外位置C。
update,transform.position=位置C+vec * deltaTime;,此时位置为D

也就是说撞墙时每次移动是在物理系统处理过的位置上再进行移动,而每次物理系统又因为间隔,和上一次的位置导致挤出的位置不同所以导致抖动。

上面说到,和物理系统的冲突不是最本质的原因,为什么?

因为这里导致抖动的根源还是因为使用了当前位置来进行计算。

假设我们把代码改成如下:
 

    private Vector3 startPos;

    private float elapsedTime;
    // Start is called before the first frame update
    void Start()
    {
        startPos = transform.position;
    }

    // Update is called once per frame
    void Update()
    {
        elapsedTime += Time.deltaTime;
        
        var targetPos = startPos + Vector3.right * 10;
        transform.position = Vector3.Lerp(startPos, targetPos, elapsedTime/10);
        
    }

        这个代码是10秒内从起始位置移动到右边10米处,他没有使用当前位置,而是每帧设置新的位置。

        

        可以看到畅通无阻的进入了方块,我没有改刚体的任何设置。这段移动中也有物理系统参与反应,并且在fixedUpdate中把它挤了出去,但是小球在update中设置新位置,所以覆盖了物理系统的挤出结果,看起来就像无视了物理系统一样。

        

        

相关文章:

  • 【算法】贪心
  • 使用Docker部署前端应用到生产环境
  • Spring生态下的中台架构设计:如何构建可扩展业务系统?
  • MOEFeedForward 模块
  • MongoDB 集群模式简单了解
  • Elasticsearch 7.x入门学习-系统架构与工作流程
  • 【商城实战(28)】揭秘推荐系统集成,开启个性化购物新时代
  • vscode 配置golang开发环境
  • ctf-web: xss 任意位置插入情况绕过 DOMPurify -- tpctf layout
  • Flutter 学习之旅 之 flutter 全屏背景图设置功能的简单实现
  • 1Panel 搭建DeepSeek-R1,开启AI自由新体验
  • Anaconda安装页面四个选项的作用
  • 【高级前端】为什么computed不起作用?有哪些使用computed 的禁忌?
  • Fiora聊天系统本地化部署:Docker搭建与远程在线聊天的实践指南
  • linux配置zabbix-agent
  • ODA模拟器实验系列之一:准备工作
  • 跟网型逆变器小干扰稳定性分析与控制策略优化simulink仿真模型和代码(包含完整仿真报告)
  • failed to load elasticsearch nodes
  • 体育赛事大数据分析:AI模型对足球大小球预测的精度优化
  • 如何用Docker容器化Java应用?Spring Boot实战指南
  • 网站建设用苹果系统与liunx/网站优化外包找谁
  • 网站中的游戏是怎么做的/流量查询网站
  • 海城网站制作建设/百度热搜榜排名昨日
  • 个人博客网站制作搭建/百度指数什么意思
  • 有没有便宜做网站的 我要做个/漳州网络推广
  • 西安网站开发有哪些公司/域名交易