Jump to content

How to differentiate ground from rocks and buildings (raycast hits)


Dunbaratu

Recommended Posts

I'm trying to make my LaserDist mod a bit smarter about reporting the kind of thing the laser has hit: ground versus building versus scatter rock (that last one is only for mods have made the scatter rocks have colliders).

The current logic is along these lines (this is a simplified version that demonstrates where I'm having a problem with a lot of the extra stuff stripped out):

RaycastHit hit = bestLateUpdateHit; // bestLateUpdateHit is populated elsewhere in the mod

GameObject hitObject = (hit.transform == null ? null : hit.transform.gameObject);
if (hitObject != null)
{
    CelestialBody body = hitObject.GetComponentInParent<CelestialBody>();
    if (body != null)
    {
        // code that handles the case where the raycast hit terrain
    }
    else
    {
        // code that handles the case where the raycast hit something other than terrain.
    }
}

The problem is that in my testing for whether the raycast hit terrain or something else, testing for CelestialBody generates false positives because in addition to being true for terrain, it's also true for space center buildings, and every other non-vessel object.  This makes sense if SQUAD has designed things so that the buildings are children of the CelestialBody just like the terrain polygons are, which of course they have to be so they can stay "glued" to the planet surface and move with it.

So what I'm looking for, is what type "T", or what set of "T"'s can I use in the call GetComponentInParent<T>() that will help me distinguish "this thing is the ground" from "this thing isn't the ground"?

I've been trying to find experimentally at runtime just what the full parent-chain looks like for my hits all the way up (i.e. this component is a member of this component which is a member of this component, etc) but the problem I'm having is that C# won't allow me to make type T in the various thingy.GetFoo<T>() calls be the open-ended GameObject type or Component type.  It insists I use a type a bit more specific than that, and the whole point of the excercise is that I don't actually know what those types are yet and I'm trying to discover them.  I haven't found in the Unity API where the call is for "just get the immediate parent, and I don't know yet what type that parent will be.  I'd like to print it at runtime."

So because I don't know the actual component tree layout SQUAD uses for terrain versus building meshes, and I haven't succeeded at finding that "just get me the parent" call so I can do my own investigation and learn it, I don't know how to discover what kind of thing my raycast has hit.

Does anyone know which type T with GetComponentInParent<T>() will find a hit for ground but not for buildings?  (or visa-versa).

 

 

Link to comment
Share on other sites

Maybe look at the layer the objects are on? (GameObject.layer)

Going to poke at this myself, if that question could be answered it would help my Landing Aid mod.

D.

edit:  It appears that everything "ground" is on layer 15, at least the PQS objects and the Launchpad models. Currently testing but it looks like that if the GameObject hit has a Component of Type "PQ", then it's a PQS object, otherwise it's a model of some sort.

edit the 2nd: Looking at your post again, the parent/child relationship appears to be through the transform objects.

So "MyGameObject.transform.parent.GameObject" is a reference to the parent GameObject.

edit the 3rd: So, it's looking pretty solid.

LayerMask testMask = 1 << 15; //cast against layer 15 only.
if (Physics.Raycast(pRayDown, out pHit, (float)(FlightGlobals.ActiveVessel.mainBody.Radius + FlightGlobals.ActiveVessel.altitude), testMask)) //cast ray
{
     if(pHit.collider.gameObject.GetComponent<PQ>() != null)
     {
        //Hit PQS
     }
     else
     {
        /Hit something else
     }
     }
}

For sure you need to ignore layer 10 (scaled space stuff) and the layer that parts themselves are on. (Forgot to note it, not sure what layer number it is.)

The wildcard is the mods that add terrain, I only tested stock against the KSC buildings and the ground (including under the oceans) near it.

 

edit the last: The annoying part is that water seems to have no collider to hit, a raycast with a LayerMask of ~0 (which should hit anything) still hits the PQS terrain on the seabed.

Also, parts attached to the current vessel appear to be on layer 0 and I'm not able to determine if seperated parts (another vessel) are also on layer 0 or not.

 

edit the next day: Looks like all actual parts are on layer zero, you have to do a if(!FlightGlobas.ActiveVessel.Parts.Contains(pHit.collider.gameObject.GetComponentUpwards<Part>()) check to see if the part you hit is on the focus vessel or not.

Edited by Diazo
Link to comment
Share on other sites

  • 1 month later...

I found this thread when looking for information about raycasts as I just happened to be going through BD armory code to try to figure out how it interacts with physicsless parts. But in any case, here's the way BD's code detects a KSC building:

DestructibleBuilding building = rayHit.collider.GetComponentInParent<DestructibleBuilding>();

I have no info on scatter or other sorts of non terrain though.

 

Edited by allmhuran
Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...