叮呤咣啷品 2020-07-31 00:51 采纳率: 0%
浏览 324

Unity中物体旋转后,Physics.Raycast进行射线碰撞检测,射线碰撞点位置更新滞后一帧?

测试工程:
链接:https://pan.baidu.com/s/1pkbETe_7vVWtYu5jXx-GOw
提取码:tybh

1、需求:右侧圆柱体会在Z轴上进行旋转,以及在Y轴方向移动,需要检测到左侧小球所在位置水平方向上与圆柱体相交的点(圆柱体内部中间);

2、方法:将圆柱体的CapsuleCollider.Radius,使射线碰撞检测是时RaycastHit.point刚好在圆柱体内部;

图片说明

3、在点击“角度”或者“位置”(圆柱非竖直时有效)时,先进行角度或者位置变化,然后进行射线碰撞检测,记录下来射线检测碰撞点,并且开启Update中的射线检测;在Update中进行碰撞检测,第一帧碰撞位置与后面帧(设置运行1秒后关闭)打印位置不同,也存在滞后一帧的情况;
图片说明

最后问题:
请问下,物体旋转或者位置发生改变时,相关顶点的位置更新时在下一帧进行?还是说Physics.Raycast中的碰撞检测也是在下一帧执行,只是执行时间早于位置顶点的更新?或者其他什么原因导致碰撞点滞后一帧?

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

public class Manager : MonoBehaviour
{
    public Transform cylinder;
    public Transform physicsRaycast;
    Vector3 initPosition;
    Vector3 initRotation;
    public Button angle;
    public Button position;
    public Button reset;
    /// <summary>
    /// 点击时,只执行射线碰撞检测,不进行角度和位置的变化;
    /// </summary>
    public Button rePhysicsRaycast;
    /// <summary>
    /// 射线碰撞到的点
    /// </summary>
    Vector3 hitPosition = Vector3.zero;
    /// <summary>
    /// 在Update中是否开始打印
    /// </summary>
    bool isDebugMessage = false;
    /// <summary>
    /// Update中开启打印时间,默认打印1s数据后停止打印
    /// </summary>
    float time = 1;

    // Start is called before the first frame update
    void Start()
    {
        initPosition = cylinder.position;
        initRotation = cylinder.localEulerAngles;

        angle.onClick.AddListener(AngleClick);
        position.onClick.AddListener(PositionClick);
        reset.onClick.AddListener(ResetClinder);
        rePhysicsRaycast.onClick.AddListener(RePhysicsRaycastClick);
    }

    void AngleClick()
    {
        Debug.Log("点击角度旋转-----前:     X1 : " + hitPosition.x + "***"
        + "Y1 : " + hitPosition.y + "***"
        + "Z1 : " + hitPosition.z);

        cylinder.localEulerAngles = new Vector3(cylinder.localEulerAngles.x, cylinder.localEulerAngles.y, cylinder.localEulerAngles.z - 10);
        UpdatePhysics("角度发生改变: ");

        Debug.Log("点击角度旋转-----后:     X2 : " + hitPosition.x + "***"
                + "Y2 : " + hitPosition.y + "***"
                + "Z2 : " + hitPosition.z);
    }

    void PositionClick()
    {
        cylinder.position = new Vector3(cylinder.position.x, cylinder.position.y + 0.2f, cylinder.position.z);
        UpdatePhysics("位置发生改变: ");
        Debug.Log("点击位置移动-----后:        X5 : " + hitPosition.x + "***"
            + "Y5 : " + hitPosition.y + "***"
            + "Z5 : " + hitPosition.z);
    }

    void ResetClinder()
    {
        cylinder.position = initPosition;
        cylinder.localEulerAngles = initRotation;
    }

    void RePhysicsRaycastClick()
    {
        UpdatePhysics("不进行位置、角度,只进行射线碰撞检测:");

        Debug.Log("不进行位置、角度,只进行射线碰撞检测:     X3 : " + hitPosition.x + "***"
                    + "Y3 : " + hitPosition.y + "***"
                    + "Z3 : " + hitPosition.z);
    }

    void UpdatePhysics(string name)
    {
        isDebugMessage = true;
        //GameObject temp1 = new GameObject(name + "temp1");
        //temp1.transform.position = hitPosition;

        //创建一条指定方向的射线
        Ray ray = new Ray(physicsRaycast.position, physicsRaycast.right * 100);
        RaycastHit hit;
        //范围内是否有碰撞
        bool isHit = Physics.Raycast(ray, out hit, 100);
        if (isHit && hit.collider.gameObject.name.Equals("Cylinder"))
        {
            hitPosition = hit.point;

            Debug.Log("射线碰撞检测-----中:     X6 : " + hitPosition.x + "***"
            + "Y6 : " + hitPosition.y + "***"
            + "Z6 : " + hitPosition.z);
            //GameObject temp2 = new GameObject(name + "temp2");
            //temp2.transform.position = hitPosition;
        }
    }

    // Update is called once per frame
    void Update()
    {
        if (isDebugMessage)
        {
            time -= Time.deltaTime;
            if(time <= 0)
            {
                isDebugMessage = false;
                time = 1;
            }
            else
            {
                //创建一条指定方向的射线
                Ray ray = new Ray(physicsRaycast.position, physicsRaycast.right * 100);
                RaycastHit hit;
                //范围内是否有碰撞
                bool isHit = Physics.Raycast(ray, out hit, 100);

                if (isHit && hit.collider.gameObject.name.Equals("Cylinder"))
                {
                    hitPosition = hit.point;

                    Debug.Log("在Update中开启射线检测:     X4 : " + hitPosition.x + "***"
                                + "Y4 : " + hitPosition.y + "***"
                                + "Z4 : " + hitPosition.z);

                    //GameObject temp2 = new GameObject(name + "temp2");
                    //temp2.transform.position = hitPosition;
                }

            }
            Debug.Log("在Update中,点击按钮后开始打印信息:     X7 : " + hitPosition.x + "***"
                        + "Y7 : " + hitPosition.y + "***"
                        + "Z7 : " + hitPosition.z);
        }
    }
}
  • 写回答

1条回答 默认 最新

  • zqbnqsdsmd 2020-07-31 09:00
    关注
    评论

报告相同问题?

悬赏问题

  • ¥15 (标签-考研|关键词-set)
  • ¥15 求修改代码,图书管理系统
  • ¥15 请问有没求偏多标签数据集yeast,reference,recreation,scene,health数据集。
  • ¥15 传感网应用开发单片机实训
  • ¥15 Delphi 关于sAlphaImageList使用问题
  • ¥15 寻找将CAJ格式文档转txt文本的方案
  • ¥15 shein测试开发会问些啥我是写java的
  • ¥15 关于#单片机#的问题:我有个课程项目设计,我想在STM32F103veTX单片机,M3主控模块上设计一个程序,在Keil uVision5(C语言)上代码该怎么编译?(嫌钱少我可以加钱,急急急)
  • ¥15 opnet仿真网络协议遇到问题
  • ¥15 在安装python的机器学习程序包scikit-learn(1.1版本)时遇到如下问题