ShimWooJeong / AR_experiment

0 stars 4 forks source link

Unity Hand Tracking에서 오브젝트 던질 때 손에서 떨어지자마자 낙하하는 문제 (질문) #19

Closed ShimWooJeong closed 2 years ago

ShimWooJeong commented 2 years ago

멘토님..~~ 제가 질문이 넘 많죠..~ 두 번째 실험의 VR포팅도 거의 다 해가고 이제 마지막 장면만이 남았습니다! 근데 마지막 남은 장면이 물건을 던져서 맞춰야 하는 장면인데 VR상에서 오브젝트를 잡고 던질 때 질문2 사진처럼 진행되었으면 하는 방향으로 포물선을 그리며 날아가는 것이 아닌, 손에서 떨어지자 마자 수직으로 떨어집니다.. 검색해서 여러가지 시도를 해봤는데 그 중에 velocity값이랑 angularVelocity값을 m_grabbedObj(잡은 오브젝트)의 rigidbody에 적용해보기도 하고 VR 물리학 던지기 개선 이 사이트는 참고하다가 스크립트에서 오류가 자꾸 나더라구요..^^ 어흑 그래서 사이트에 있는 방법은 완벽히 적용해보지는 못 했습니다. 물론 velocity값이랑 angularVelocity값 적용하는 것도 아무런 변화가 없고 물체 rigidbody의 Mass(질량?)을 낮춰봐도.. 안 돼요.. 저번주 수요일부터 시도해봤는데 어디서부터 문제인 건지 유튜브만 보면 다른 유튜버들은 잘만 던지던데 모르겠어서 여쭤봅니다 뭔가 손이 휘둘러지는 방향으로 오브젝트에 힘을 주어 날려야할 것만 같기도 하고 그런데 그냥 addforce를 사용해야 할까요?

ShimWooJeong commented 2 years ago

For those who are struggling with the linear velocity being zero which makes the OVRGrabbable to stop when you release it, I finally found the definitive solution. It's quite a stupid mistake of the Oculus developers on the OVRGrabber script. 3 simple steps:

1 - Update the line of code in the Start Method that is setting the m_ParentTransform in a wrong way (in my case they were setting the parent to the transform itself), simply make sure that if the parent isn't null you set it to 'this.transform.parent' and not to 'this.transform'.

2 - Update all occurrences of the script which set the variables 'm_lastPos' and 'm_lastRot' to actually store the m_parentTransform value instead of the transform itself (because the anchor (the parents) are the ones that actually are updated, not the hands by themselves). Make sure in the Start method to move those two lines after the block of code which sets the m_parentTransform, otherwise you will get a NullReferenceException.

3 - Finally, and the major issue which caused the object to stop (in my case, when I fixed it, everything worked properly) it's because in the Start method also, there's some piece of code that calls the function UpdateAnchors only when they are updated by binding an event of the OVRRig, you can just get rid of that block and, in the Update method, ALWAYS call the UpdateAnchors method, and not only when the condition is met (basically, remove the conditional). Then on the HandTrackingGrabber make sure to update the lines that calculate the velocities with also the 'm_transformParent' instead of the 'this.transform'.

These 3 steps solved my problem and I think it's a very logical solution, now it works like a charm! Sorry if my english is quite bad, it's not my native language :')

계속 시도해보던 중 한 유튜버의 HandTracking Grab 관련 영상 댓글 중에서도 비슷한 현상 같길래 따라해봐도 안 되네요..~ 이건 좀 희망을 가져봤는데 말이예요...~

jongfeel commented 2 years ago

안녕하세요. 오히려 계속해서 질문 주시는게 더 좋아요.

음 마지막에 힌트가 있는데 공의 rigidbody.AddForce() 를 사용하면 해결이 될거에요. 어렵지 않은 함수니까 찾아보고 하면 금방 될겁니다.

관련된 것도 검색하면 금방 나옵니다 ㅎㅎ 심지어 unity 던지기 이렇게 검색해도 나와요.

ShimWooJeong commented 2 years ago

손에 넣는 스크립트인 HandTrackinGrabber에 addforce를 넣어보고

protected override void GrabEnd()
    {
        if (m_grabbedObj)
        {
            //Vector3 linearVelocity = (m_parentTransform.position - m_lastPos) / Time.fixedDeltaTime;
            //Vector3 angularVelocity = (m_parentTransform.eulerAngles - m_lastRot.eulerAngles) / Time.fixedDeltaTime;
            Vector3 linearVelocity = (transform.parent.position - m_lastPos) / Time.fixedDeltaTime;
            Vector3 angularVelocity = (transform.parent.eulerAngles - m_lastRot.eulerAngles) / Time.fixedDeltaTime;

            GrabbableRelease(linearVelocity, angularVelocity, controllerCenterOfMass);

            Rigidbody r = m_grabbedObj.GetComponent<Rigidbody>();

            r.useGravity = true; 
            r.isKinematic = false;

            r.velocity = linearVelocity;
            r.angularVelocity = angularVelocity;

            Vector3 speed = new Vector3(0, 200, 2000);

            //r.AddForce(Vector3.forward * power);
            r.AddForce(speed);
        }

        GrabVolumeEnable(true);
    }

그냥 OVRGrabber에도 addforce를 넣어봤는데도 똑같네요ㅠㅠ 제가 잘못 응용한 건가욕..??

 virtual protected void GrabEnd()
    {
        if (m_grabbedObj != null)
        {
            OVRPose localPose = new OVRPose { position = OVRInput.GetLocalControllerPosition(m_controller), orientation = OVRInput.GetLocalControllerRotation(m_controller) };
            OVRPose offsetPose = new OVRPose { position = m_anchorOffsetPosition, orientation = m_anchorOffsetRotation };
            localPose = localPose * offsetPose;

            OVRPose trackingSpace = transform.ToOVRPose() * localPose.Inverse();
            Vector3 linearVelocity = trackingSpace.orientation * OVRInput.GetLocalControllerVelocity(m_controller);
            Vector3 angularVelocity = trackingSpace.orientation * OVRInput.GetLocalControllerAngularVelocity(m_controller);
            linearVelocity *= throwGain;

            Vector3 controllerVelocityCross = Vector3.Cross(angularVelocity, m_grabbedObjectPosOff - controllerCenterOfMass);

            GrabbableRelease(linearVelocity, angularVelocity, controllerVelocityCross);

            Vector3 speed = new Vector3(0, 200, 2000);

            //r.AddForce(Vector3.forward * power);
            Rigidbody r = m_grabbedObj.GetComponent<Rigidbody>();
            r.AddForce(speed);
        }

        // Re-enable grab volumes to allow overlap events
        GrabVolumeEnable(true);
    }
ShimWooJeong commented 2 years ago

저 시간부터 지금까지 시도중입니다.. 흑흑 여러 시도 중 오브젝트를 놓을 때 오브젝트의 속도를 계산하기 위해서

이 현상을 녹화해서 보여드리려고 유튜브에 업로드 해봤습니다,,~~ https://youtu.be/bjR_JJ9_7pQ

jongfeel commented 2 years ago

제 생각에는 힘조절만 하면 다 한거 같은데요?

보면 speed의 값이 어마무시한 값으로 설정되어 있는데 수치를 좀 조절하면 좋을 것 같고 한가지 더 알려드리면 두 번째 파라미터에 ForceMode를 Impulse로 해보세요

AddForce(speed, ForceMode.Impulse);

콩알탄은 순간 가속도이고 어딘가에 충돌해서 폭발해야 하는 오브젝트니까 impulse 모드로 하면 적당할 거 같습니다.

ShimWooJeong commented 2 years ago

총을 쏘는 것처럼 날라가버릴 때는 addforce를 주석처리한 상태였습니다! addforce는 HandTrankinGrabber 코드에 넣은 것이 아니라 OVRGrabber에 넣었었던 거였습니다. 총처럼 쏴지는 코드는 HandTrakinGrabber에 있는 코드예요.

Vector3 linearVelocity = (m_grabbedObj.transform.position - m_lastPos) / Time.fixedDeltaTime;
Vector3 angularVelocity = (m_grabbedObj.transform.eulerAngles - m_lastRot.eulerAngles) / Time.fixedDeltaTime;

이 코드를 쓰고 나서 총처럼 날라가서요.. 저 addforce를 OVR Grabber의 Grab End 속에 작성했었는데 시도해 본 결과 원래 질문할 때랑 똑같았습니다!..ㅠㅠ 그냥 오브젝트랑 손이랑 충돌하면 물체에 붙은 스크립트에 addforce를 달아서 날아가도록 설정은 했습니다만.. VR 특성상 좀 더 몸을 쓰도록 하고 싶어서 실제 공을 던지는 것처럼 하고 싶었는데..흑흑.. 일단 백신 일정+추석 연휴 때문에 본가에 올라와서 다음주에 내려가서 다른 시도를 더 해보려고 합니다!.. 추석 연휴 잘 보내세요!