Search Unity

  1. Unity 2019.1 beta is now available.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. We're looking for insight from anyone who has experience with game testing to help us better Unity. Take our survey here. If chosen to participate you'll be entered into a sweepstake to win an Amazon gift card.
    Dismiss Notice
  4. On February 28th the Feedback website will shut down and be redirected to the Unity forums. See the full post for more information.
    Dismiss Notice
  5. Want to provide direct feedback to the Unity team? Join the Unity Advisory Panel.
    Dismiss Notice
  6. Unity 2018.3 is now released.
    Dismiss Notice
  7. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice

Placing prefabs on other objects without raycasts?

Discussion in 'Extensions & OnGUI' started by FeastSC2, Jun 25, 2018.

  1. FeastSC2

    FeastSC2

    Joined:
    Sep 30, 2016
    Posts:
    525
    Whenever building tools to place prefabs quickly in your scene, it's common to use raycasting on some collider to know where the prefab should be created. For example in 3D, we raycast on a terrain to place the prefab directly on top of the terrain.

    I wanted to use the same concept for 2D: I double click with my mouse and it places the prefab on a pre-existing prefab if there are any, if not it goes to Z:0.

    The problem I have is that I don't want my 2d prefabs to have a 2d colliders as these colliders are not used in my game. So how can I detect if there is a sprite where I'm clicking on without using raycasts (specifically without using colliders on the sprites in my scene).
     
  2. Madgvox

    Madgvox

    Joined:
    Apr 13, 2014
    Posts:
    523
    Without implementing your own mesh or shader raycasting, the best in-built method to pick objects is the appropriately named HandleUtility.PickGameObject.
     
    FeastSC2 likes this.
  3. FeastSC2

    FeastSC2

    Joined:
    Sep 30, 2016
    Posts:
    525
    Since I would like to know about multiple gameobjects in the cursor's direction, as if a line was cast from the mouse cursor towards infinity in the direction of: from the sceneView camera to the cursor. Is there something else I can use that achieves this?

    Here's how I previously did this with raycast:

    Code (CSharp):
    1.         Ray worldRay = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
    2.         var result = Physics.RaycastAll(worldRay, 100000f);
     
  4. Madgvox

    Madgvox

    Joined:
    Apr 13, 2014
    Posts:
    523
    If you still want to avoid implementing your own mesh raycasting system, you could add temporary colliders with hideFlags to your objects and raycast against them.

    However for maximum flexibility you'll probably want to be able to raycast against meshes. I've actually implemented this for my own projects. It's not actually that difficult, mainly just porting to C# some algorithms made by way smarter people than I. :)

    This is the algorithm I used for broad-phase collision: http://www.realtimerendering.com/resources/RTNews/html/rtnv21n1.html#art9
    This is the algorithm I used for triangle intersection: https://www.cs.utah.edu/~aek/research/triangle.pdf

    Here's an example of it in action (this mesh has no collider):
     
    FeastSC2 likes this.
  5. FeastSC2

    FeastSC2

    Joined:
    Sep 30, 2016
    Posts:
    525
    I ended up succeeding to make it for what I needed with the simple HandleUtility.PickGameObject. The answer simply was using what you suggested and the ignoreObjects argument.


    Code (CSharp):
    1.         List<GameObject> ignoreList = new List<GameObject>();
    2.         var obj = HandleUtility.PickGameObject(Event.current.mousePosition, false);
    3.         if (obj)
    4.         {
    5.             while (LayerHelper.IsLocked(obj.layer)) // Don't place prefab on GameObjects with locked layers
    6.             {
    7.                 ignoreList.Add(obj);
    8.                 obj = HandleUtility.PickGameObject(Event.current.mousePosition, false, ignoreList.ToArray());
    9.             }
    10.         }
    That's a very cool result you got there! I'll make sure to implement this when I create a 3d game myself : )
     
    Madgvox likes this.