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
6
Question by aliakbo · Feb 09, 2012 at 02:13 PM · raycastcollidermousecollidersselecting objects

Raycast Without Colliders

Basically, I want to select objects with the left mouse button. My objects do not have and should not have colliders.

Now if they did, selecting them using

  if (Physics.Raycast(ray.origin, ray.direction, out hit))

is pretty simple.

How would I go about doing this as my objects don't have colliders?

Comment
Add comment · Show 7
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 flamy · Feb 09, 2012 at 02:23 PM 0
Share

is it perspective camera or orthographic!!?

avatar image aliakbo · Feb 09, 2012 at 04:02 PM 0
Share

$$anonymous$$y camera is perspective, but how is that relevant?

avatar image flamy · Feb 09, 2012 at 04:05 PM 0
Share

if it is orthograpic it is easy to get the bounding rectangle on screen and check if the object is hit (without any colliders)

avatar image jonbro · Feb 09, 2012 at 04:07 PM 1
Share

if your camera was orthographic, then testing for collisions with your objects would be a simple matter of comparing the x,y of the mouse point and then doing either a square or circle (or some other complex shape) collision test. Since you don't have a orthographic camera, you need to take into account the FOV, because depending on depth, the x/y of the mouse point are different.

The basic method is construct a Vector3 that describes the position of the mouse on the screen, then move it forward away from the camera slowly until the vector is inside of one of your objects. There are some optimizations that you can do to this. This is the work that the collider handles.

avatar image flamy · Feb 09, 2012 at 04:12 PM 0
Share

indeed jonbro explained it well

Show more comments

6 Replies

· Add your reply
  • Sort: 
avatar image
13
Best Answer

Answer by Loius · Apr 19, 2013 at 08:46 PM

Put colliders on them anyway. Then set the colliders to a different physics layer and make that layer non-collisive with every layer (including itself) (Edit > Project Settings > Physics). Then use layer-based raycasts to find them. :)

Comment
Add comment · Show 3 · 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 cregox · Apr 19, 2013 at 09:09 PM 1
Share

Still, at very least, not a good solution for animated skinned mesh (which is basically any animations with bone, I believe). Supposing you can actually use a mesh collider there (which is possible).

avatar image Loius · Apr 20, 2013 at 05:18 AM 1
Share

How's that not good? Slam a few non-colliding simple colliders on the bones and voila.

You never* want an animated-mesh-collider in a game environment. It's just ridiculously slow to modify the collision data all the time. I suppose if you're in the realm of simulation where accuracy is more important than time, that would be great.

*mostly never

avatar image OP_toss · Dec 05, 2014 at 07:01 PM 0
Share

What if it literally doesn't work to use colliders?

Case in point, I need to raycast a ring, and making a mesh that's a ring means a concave mesh collider, which apparently ignores raycasts, as I've proven through rigorous testing.

$$anonymous$$y only alternative thought was to render to a texture and check the color under the mouse position. I could use unique colors in order to deter$$anonymous$$e which object I'm under. But I'm wary of the cost associated with this option...

Thoughts?

avatar image
4

Answer by Benproductions1 · Feb 02, 2013 at 02:34 AM

Look at this Threadpost: http://forum.unity3d.com/threads/14378-Raycast-without-colliders It explains in detail how to implement your own raycasting algorithm, only using triangle information and no colliders.

Comment
Add comment · Show 4 · 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 cregox · Apr 19, 2013 at 05:00 PM 0
Share

I believe the thread does require colliders, despite the title.

avatar image Benproductions1 · Sep 03, 2013 at 04:44 AM 0
Share

@Cawas You are wrong. The whole point is that it is a reimplementation of raycasting in Unity

avatar image cregox · Sep 04, 2013 at 12:01 AM 0
Share

@Benproductions1 you're probably right. Sometimes I don't even know what I wrote.

avatar image cregox · Sep 04, 2013 at 05:33 AM 0
Share

I haven't earned my God powers yet...

avatar image
2

Answer by jaxx0rr · Sep 01, 2013 at 12:08 PM

turn on IS TRIGGER option on collider .. perfect

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 cregox · Sep 02, 2013 at 04:07 PM 0
Share

Same problem as with Louis's suggestion.

avatar image Benproductions1 · Sep 03, 2013 at 04:44 AM 0
Share

@Cawas and @Loius suggested a way around it. Read his comment and accept his answer if it helped

avatar image
1

Answer by drudiverse · Jun 26, 2014 at 08:16 AM

STRANGE SOLUTION: to raycast via pixel color, so you can check if you hit a visible pixel of an object...

Make a small sphere with preferably the same color regardless of lighting and textures, I don't know how that is done, perhaps pink sphere of shaderless unity objects...

If you click with the mouse, then scan a ray in a line from the camera by moving the pink sphere backwards and forwards through space, and see if it gets covered up by a pixel of a different color:

 Place sphere 1 meter away... if pixel = pink:
 place sphere 1000 meters away, if pixel != pink:
 place sphere 500 meters away, if pixel = pink:
 place sphere 750 meters away... etc. 

In this way you can devide the distance where the collider object is in 2 and slowly narrow down to the precise point in space where the pink object is covered by another object.

if you devide 3000m by 2 many times, it takes 16 steps to find your collision object to within 0.1 meters... so perhaps 16 frames, and say 10 steps to search 200 meters range.

If it is necessary to take 16 frames, i dont know. perhaps it can be done in one frame?

Anyways, when you have the location of the collision pixel, you can go through all the objects on the screen, compare their position, perhaps compare all the triangles on the screen if you want to be very precise. it would be convenient to have a list of triangles in a particular point in space!?

If someone has advice about the above implementation, and ways to refine it or think's it's abit nonsense, I would be very interestested to have it optimised!

Comment
Add comment · Show 1 · 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 drudiverse · Jun 26, 2014 at 08:29 AM 0
Share

for distance precision the pink sphere should be a flat square.

avatar image
1

Answer by Xelnath · Aug 29, 2015 at 07:33 PM

I found the solution of "just throw a mesh collider on it" to not be acceptable.

However, it is probably the right call for anything runtime. If you want something for the editor, use this. (Caveats included: This was designed for a 2d system to enable dragging in the 2d plane from a 3d camera view.)

Hopefully, someone will take the information here and distill it into a reusable form:

 using UnityEngine;
 using UnityEditor;
 using System.Collections;
 using System;
 using System.Reflection;
 using System.Linq;
 using System.Collections.Generic;
 
 [CustomEditor(typeof(BaseUnit), true)]
 public class ClickBaseUnitEditor : Vexe.Editor.Editors.BaseBehaviourEditor
 {
     public static bool blockingMouseInput = false; 
     public static Vector3 offset = Vector3.zero;
 
     public const string SuspendedBuff = "_EDITOR_Suspended";
     public void SuspendUnit(BaseUnit unit)
     {
         if ( Application.isPlaying )
         { /// custom stuff    
         }
     }
     public void ReleaseUnit(BaseUnit unit)
     {/// custom stuff
     }
 
     public static Ray GetMouseClickRay()
     {
         Event e = Event.current;
         var camera =  SceneView.lastActiveSceneView.camera;
 
         var mousePosition = e.mousePosition;
         mousePosition.y = camera.pixelHeight - mousePosition.y;
         var ray = camera.ScreenPointToRay(mousePosition);
 
         return ray;
     }
 
     public static bool MouseClickRaycheckSpineObjects(out IList<BaseUnit> spineUnitsFound, out IList<Vector3> hits)
     {
         var ray = GetMouseClickRay();
         var spineObjs = Transform.FindObjectsOfType<SkeletonAnimation>();
         spineUnitsFound = new List<BaseUnit>();
         hits = new List<Vector3>();
         //Debug.DrawRay(ray.origin, ray.direction * 80f + new Vector3(0.1f,0f,0f), Color.blue,10);
 
         foreach ( var spineGameObj in spineObjs )
         {
             var root = spineGameObj.transform.position;
             var intersectFound = false;
             var meshFilter = spineGameObj.GetComponent<MeshFilter>();
             if ( meshFilter != null )
             {
                 var mesh = meshFilter.sharedMesh;
                 for ( int subMeshIndex  = 0; subMeshIndex < mesh.subMeshCount; subMeshIndex ++ )
                 { 
                     var triangles = mesh.GetTriangles(subMeshIndex);
                     for ( int iTriBegin = 0; iTriBegin < triangles.Length; iTriBegin += 3 )
                     {
                         Vector3 a, b, c;
                         a = mesh.vertices[triangles[iTriBegin]];
                         b = mesh.vertices[triangles[iTriBegin+1]];
                         c = mesh.vertices[triangles[iTriBegin+2]];
 
                         a = spineGameObj.transform.TransformPoint(a); 
                         b = spineGameObj.transform.TransformPoint(b); 
                         c = spineGameObj.transform.TransformPoint(c); 
 
                         if ( Intersect(a, b, c, ray) )
                         {
                             intersectFound = true;
                             break;
                         }
                     }
 
                     if ( intersectFound ) break;
                 }
             }
 
             if ( intersectFound )
             {
                 var baseUnit = spineGameObj.GetComponentInParent<BaseUnit>();
                 if ( baseUnit )
                 { 
                     var plane = new Plane( Vector3.back, spineGameObj.transform.position );
                     Vector3 p = Vector3.zero;
                     float rayDistance;
                     if ( plane.Raycast(ray, out rayDistance )) {
                         p = ray.GetPoint(rayDistance);                    
                     }
 
                     if ( baseUnit.gameObject == Selection.activeGameObject )
                     {
                         spineUnitsFound.Insert(0, baseUnit);
                         hits.Insert(0, p);
                     }
                     else
                     {
                         spineUnitsFound.Add(baseUnit);
                         hits.Add( p);
                     }
                 }
             }
         }
 
         if ( spineUnitsFound.Count > 0 ) 
             return true;
 
         return false;
     }
     public static bool MouseClickRaycheckBaseUnit(out IList<BaseUnit> unitsFound, out IList<Vector3> hits)
     {
         var ray = GetMouseClickRay();
         var coll = Physics2D.RaycastAll(ray.origin, ray.direction, Mathf.Infinity);
 
         //Debug.DrawRay(ray.origin, ray.direction * 80f + new Vector3(0.1f,0f,0f), Color.blue,10);
 
         unitsFound = new List<BaseUnit>();
         hits = new List<Vector3>();
 
         foreach ( var c in coll )
         {
             var baseUnit = c.collider.gameObject.GetComponentInParent<BaseUnit>();
             if ( baseUnit )
             { 
                 var plane = new Plane( Vector3.back, baseUnit.transform.position);
                 Vector3 p = Vector3.zero;
                 float rayDistance;
                 if ( plane.Raycast(ray, out rayDistance )) {
                     p = ray.GetPoint(rayDistance);                    
                 }
 
                 if ( baseUnit.gameObject == Selection.activeGameObject )
                 {
                     unitsFound.Insert(0, baseUnit);
                     hits.Insert(0, p);
                 }
                 else
                 {
                     unitsFound.Add(baseUnit);
                     hits.Add( p);
                 }
             }
         }
 
         IList<BaseUnit> spineUnitsFound;
         IList<Vector3> spineHits;
         var anythingFound = MouseClickRaycheckSpineObjects( out spineUnitsFound, out spineHits );
 
         if ( anythingFound )
         {
             for ( int i = 0; i < spineUnitsFound.Count; i ++ )
             {
                 var baseUnit = spineUnitsFound[i];
                 var p = spineHits[i];
                     
                 if ( unitsFound.Contains(baseUnit) )
                     continue;
 
                 if ( baseUnit.gameObject == Selection.activeGameObject )
                 {
                     unitsFound.Insert(0, baseUnit);
                     hits.Insert(0, p);
                 }
                 else
                 {
                     unitsFound.Add(baseUnit);
                     hits.Add( p);
                 }
             }
         }
 
         if ( unitsFound.Count > 0 )
             return true;
 
         return false;
     }
 
     public static bool MouseClickRaycheckAgainstBaseUnitPlane(BaseUnit b, out Vector3 intersect)
     {
         intersect = Vector3.zero;
         var plane = new Plane( Vector3.back, b.transform.position);
         /*
         var camera =  SceneView.lastActiveSceneView.camera;
         var mousePosition = Event.current.mousePosition;
         mousePosition.y = camera.pixelHeight - mousePosition.y;
         var ray2 = camera.ScreenPointToRay(mousePosition);
         */
         var ray = GetMouseClickRay();
 
 
         float rayDistance;
 
         if ( plane.Raycast(ray, out rayDistance )) {
             intersect = ray.GetPoint(rayDistance);
             return true;
         }
         return false;
     }
 
     private void OnSceneGUI( )
     {
         Event e = Event.current;
         var controlID = GUIUtility.GetControlID(FocusType.Passive);
         var type = e.GetTypeForControl(controlID );
         var selection = Selection.activeGameObject;
 
         switch ( type )
         {
             case EventType.MouseDown:
                 GUIUtility.hotControl = controlID;
                 //Debug.Log("Mouse Down");
 
                 IList<BaseUnit> unitsFound;
                 IList<Vector3> hits;
                 var anythingFound = MouseClickRaycheckBaseUnit(out unitsFound, out hits);
 
                 if ( anythingFound && unitsFound[0].gameObject == Selection.activeGameObject )
                 {
                     Debug.Log("You clicked on:" + unitsFound[0]);
                     offset = unitsFound[0].transform.position - hits[0];
                     blockingMouseInput = true;
                     e.Use();
                 }
                 else if ( anythingFound ) 
                 {
                     Selection.activeGameObject = unitsFound[0].gameObject;
                 }
                 else
                 {
                     Selection.activeObject = null;
                 }
 
 
                 break;
             case EventType.MouseMove:
             case EventType.MouseDrag:
                 if ( blockingMouseInput )
                 { 
                     if ( selection )
                     {
                         var baseUnit = selection.gameObject.GetComponentInParent<BaseUnit>();
                         Vector3 p;
                         if ( MouseClickRaycheckAgainstBaseUnitPlane(baseUnit, out p) )
                         {
                             //Debug.Log("Dragging to "+p);
                             baseUnit.gameObject.transform.position = p + offset;
 
                             SuspendUnit( baseUnit );
                             e.Use();
                         }
                         //Debug.Log("Mouse " + type + " | " + e.mousePosition);
                     }
                 }
                 break;
             case EventType.MouseUp:
                 GUIUtility.hotControl = 0;
                 //Debug.Log("Mouse Up");
                 blockingMouseInput = false;
                 break;
         }        
      }
 
      /// <summary>
      /// Checks if the specified ray hits the triagnlge descibed by p1, p2 and p3.
      /// Möller–Trumbore ray-triangle intersection algorithm implementation.
      /// </summary>
      /// <param name="p1">Vertex 1 of the triangle.</param>
      /// <param name="p2">Vertex 2 of the triangle.</param>
      /// <param name="p3">Vertex 3 of the triangle.</param>
      /// <param name="ray">The ray to test hit for.</param>
      /// <returns><c>true</c> when the ray hits the triangle, otherwise <c>false</c></returns>
      public static bool Intersect(Vector3 p1, Vector3 p2, Vector3 p3, Ray ray)
      {
          // Vectors from p1 to p2/p3 (edges)
          Vector3 e1, e2;  
  
          Vector3 p, q, t;
          float det, invDet, u, v;
  
  
          //Find vectors for two edges sharing vertex/point p1
          e1 = p2 - p1;
          e2 = p3 - p1;
  
          // calculating determinant 
          p = Vector3.Cross(ray.direction, e2);
  
          //Calculate determinat
          det = Vector3.Dot(e1, p);
  
          //if determinant is near zero, ray lies in plane of triangle otherwise not
          if (det > -Mathf.Epsilon && det < Mathf.Epsilon) { return false; }
          invDet = 1.0f / det;
  
          //calculate distance from p1 to ray origin
          t = ray.origin - p1;
  
          //Calculate u parameter
          u = Vector3.Dot(t, p) * invDet;
  
          //Check for ray hit
          if (u < 0 || u > 1) { return false; }
  
          //Prepare to test v parameter
          q = Vector3.Cross(t, e1);
  
          //Calculate v parameter
          v = Vector3.Dot(ray.direction, q) * invDet;
  
          //Check for ray hit
          if (v < 0 || u + v > 1) { return false; }
  
          if ((Vector3.Dot(e2, q) * invDet) > Mathf.Epsilon)
          { 
              //ray does intersect
              return true;
          }
  
          // No hit at all
          return false;
      }
 }
 

Comment
Add comment · 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
  • 1
  • 2
  • ›

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

14 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

Related Questions

OnCollisionEnter2D is not working 0 Answers

[2D] Raycast to mouse cursor = offset on Y axis 0 Answers

RaycastHit2D hits "itself" 3 Answers

Object movement, collider and Physics. 0 Answers

How can I let the ray to the edge of the capsule? 1 Answer


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