Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Pi_3.14 · Mar 02, 2014 at 05:16 PM · collisionerrorcapsulecollider

False-positive Collision between Eye-Ray and Capsule Collider

I have a key on the origin, which can be pointed towards 12 clock points on the XZ plane, or straight upwards:

![Alt text](/storage/temp/22972-screen+shot+2014-03-02+at+16.55.35.png)

The key has a capsule collider, so I can check when the user clicks on it:

 void Update( )
 {
     if( Input.GetMouseButtonDown( 0 ) ) 
         tryTouchPoint( Input.mousePosition );
 }


 void tryTouchPoint( Vector3 p ) 
 {
     Ray ray = Camera.main.ScreenPointToRay( p );

     RaycastHit hitResult;

     if( key.collider.Raycast( ray, out hitResult, 1000.0f ) )
     {
         Debug.DrawLine (ray.origin, hitResult.point);
         Debug.Break();
         :
     }


It does correctly register on-target clicks.

However, it is possible to create a situation where it also registers false positives: a ray that clearly misses the capsule can trigger a collision.

It's easiest to show it in a video: http://screencast.com/t/QNMQodecGnV0

EDIT: Complete key rotation code here:

// http://forum.unity3d.com/threads/54720-Gold-texture-on-iphone

 using UnityEngine;
 using System.Collections;

 public class KeyScript : MonoBehaviour 
 {
     public int currKey;
     
     float tKeyChange;
     
     float xRot = 0f, yRot = 0f, zRot = 0f;

     enum Status { Idle, Spinning, Transitioning };
     Status m_status = Status.Idle;

     // better than doing FindObjectOfType(typeof(X)) from client
     static public KeyScript singleInstance;
     void Awake( ) {
         singleInstance = this;
         newQuat = Quaternion.identity;
         m_status = Status.Idle;
         currKey = -1;
     }
     
     public bool isSpinning { get { return m_status == Status.Spinning; } }

 //    public void Toggle( ) {
 //        if( m_status == Status.Spinning )
 //            m_status = Status.Idle;
 //        else
 //            m_status = Status.Spinning;
 //    }

     public void Spin( )
     {
         m_status = Status.Spinning;
     }

     Quaternion oldQuat, newQuat;

     // Update is called once per frame
     void Update () 
     {
 //        float scale = Wheel.btnScale / 9.0f;
 //        
 //        transform.localScale = new Vector3( scale, scale, scale );

         switch( m_status )
         {
         case Status.Idle:
             break;

         case Status.Spinning:
             float rotSpeed = 60f;
             xRot += Time.deltaTime * rotSpeed;
             while( xRot > 360f )
                 xRot -= 360f;
             transform.rotation = ConstructRot( xRot, yRot, zRot );
             break;

         case Status.Transitioning:
             float t = Mathf.InverseLerp( tKeyChange, tKeyChange + 0.3f, Time.time );

             Quaternion foo = Quaternion.Slerp( oldQuat, newQuat, t );

             if( t == 1f )
                 m_status = Status.Idle;

             transform.rotation = foo;
             break;
         }
     }

     public void SetKey( int k )
     {
         m_status = Status.Transitioning;
         tKeyChange = Time.time;
         currKey = k;

         if( k == -1 )
         {
             xRot = 0f;
             yRot = 0f;
             zRot = 90f;
         }
         else{
             xRot = 0f;
             yRot = 360f * (float)(k-0f) / 12f;
             zRot = 0f;
         }

         oldQuat = transform.rotation;
         newQuat = ConstructRot( xRot, yRot, zRot );
     }


     Quaternion ConstructRot( float xRot, float yRot, float zRot )
     {
         Quaternion firstXRot = Quaternion.AngleAxis( xRot, Vector3.forward );
         Quaternion nowYRot = Quaternion.AngleAxis( yRot, Vector3.up );
         Quaternion finallyZRot = Quaternion.AngleAxis( zRot, Vector3.right );

         return finallyZRot * ( nowYRot * firstXRot );
     }
 }

EDIT: Main code:

 void Update( )
 {
     float secs_per_frame = Time.deltaTime;
     float fps = 1f / secs_per_frame;
     
     fps_smooth = Mathf.Lerp( fps_smooth, fps, 0.1f );
     
     CheckForUserInput( );
 }
 
 
 void CheckForUserInput( ) 
 {
     
     // mouse L button    
     if( Input.GetMouseButtonDown( 0 ) ) 
         tryTouchPoint( Input.mousePosition );
 }


 void OnGUI( )
 {
     if( GUILayout.Button( "BUG" ) )
         fail();
 }

 void fail()
 {
     RaycastHit hitResult;

     key.gameObject.transform.rotation = new Quaternion(0.7071068f,0f,0f,0.7071068f);

     Ray ray = new Ray( 
                       new Vector3(0.03398795f, 9.7f, -0.05699179f) , 
                       new Vector3(0.1106194f, -0.9764f, -0.1854893f)
                       );

     if( key.collider.Raycast( ray, out hitResult, 1000.0f ) )
         Debug.Log( "Got teh bug!" );
     else
         Debug.Log( " no collision wtf " );
 }

 void tryTouchPoint( Vector3 p ) 
 {
     Ray ray = Camera.main.ScreenPointToRay( p );

     Debug.DrawLine( ray.origin, ray.origin + (ray.direction * 1024f) );

     RaycastHit hitResult;

     if( key.collider.Raycast( ray, out hitResult, 1000.0f ) )
     {
         //if( ! key.isSpinning )
         Quaternion Q = key.gameObject.transform.rotation;
         Vector3 O = ray.origin, D = ray.direction;

         string LogString = string.Format( "Quaternion: ({0}f, {1}f, {2}f, {3}f), Ray Origin: ({4}f, {5}f, {6}f), Ray Direction: ({7}f, {8}f, {9}f)",
                   Q.x, Q.y, Q.z, Q.w,
                   O.x, O.y, O.z,
                   D.x, D.y, D.z
                   );
                  
         Debug.Log( LogString );


         if( key.isSpinning ) SetKey( -1 ); 
         else key.Spin( );

         return;
     }

     float dWinner = 1234567;
     int winner = 0;
     for( int i=0; i < allGems.Length; i++ )
     {
         GlowGem G = allGems[ i ];

         float dist = DistBetween( ray, G.transform.position );

         if( dist < dWinner )
         {
             dWinner = dist;
             winner = i;
         }
     }

     if( dWinner < 1f ) 
     {
         if( key.isSpinning ) {
             SetKey( winner );
         }
         else {
             allGems[ winner ].UserHit( );
     
             if( noteHit_User_Event != null )
                 noteHit_User_Event( winner );
         }
     }
 }
 
 void SetKey( int k )
 {
     key.SetKey( k );

     //float [] s = new float[] { 10,3,7,3,7,7,3,7,3,7,3,7 };

     for( int deg=0; deg < 12; deg++ ) { // scale degree; 0 is tonic etc
         //float size = ( k == -1 ) ? 0.8f : new float[] { 10,3,7,3,7,7,3,7,3,7,3,7 }[ deg ] / 10f;
         int toneme = ( k == -1 ) ? deg : ( k + deg ) % 12; // offset from keynote

         allGems[ toneme ].SetDegree ( ( k == -1 ) ? 2 : deg );
     }

     if( k > -1 )
         allGems[ k ].UserHit( );
 }


[1]: /storage/temp/22972-screen+shot+2014-03-02+at+16.55.35.png

screen shot 2014-03-02 at 16.55.35.png (62.8 kB)
Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Pi_3.14 · Mar 03, 2014 at 11:17 PM 0
Share

$$anonymous$$oved to: http://forum.unity3d.com/threads/232061-Quaternion-Capsule-Ray-Collision-bug!

1 Reply

· Add your reply
  • Sort: 
avatar image
1

Answer by Owen-Reynolds · Mar 02, 2014 at 06:50 PM

The coordinate systems seem fine: screenPointToRay gives a ray in world space, and ray casts work in world space. Collider.raycast, I think, is just an faster/alternate way of doing a standard raycast on just one object, w/o having to use layerMasks. I'm pretty sure it's still in world space (not Object space AKA local coordinate system.) And, if the math was wrong, it would probably be really wrong.

I'm wondering if it isn't an out-of-order problem. Like, each frame your code puts the key on it's side, then does the raycast to hit the tip, then snaps it upwards. More testing might find a pattern. Are the false hits always in a certain area and consistant? Sporadic?

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Pi_3.14 · Mar 02, 2014 at 07:13 PM 0
Share

I just managed to get a reproducible fail; I've added a screencast to my post.

avatar image Owen-Reynolds · Mar 03, 2014 at 09:17 PM 0
Share

I want to say it's just a coding problem somewhere. That the key really does "snap" sometimes, fast enough it's not noticeable, and the glitch is only during this snap, when the key is incorrectly sideways. But that would be only for a frame or two.

Like, oldQuat doesn't seem to always be current? $$anonymous$$aybe always compare the angle between old and new rotation each frame and look for jumps? EulerAngles are junk to work with, but I'd rather print them for a debug then Q.x/y/z (since you can enter✓ euler angles.)

$$anonymous$$aybe have the game pause on each raycast (and resume when you press x?)

It could be a raycast thing, but I get many more misses when it should hit, than hits when it should miss. Just in case, you might convert to Physics raycast and check for the $$anonymous$$ey (you should get the exact same, glitchy, results.)

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

21 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Collision Detection in Capsule Collider 0 Answers

Raycast doesn't collide as it should 1 Answer

Scene Audio Script Error 2 Answers

physics rolling error( included sample and simple demo) 0 Answers

Using GetComponent Within OnTriggerEnter 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges