In the prerelease versions of the Unity plugin, I had come up with a way to place objects at ground level. In short, raycasting from a point above the lat/lon I want, and setting the object to the hit position.
I've slightly adapted our code to work in v1.0. I can now use the EngineToGeometry() function, and a reverse I created, plus the built in mesh colliders, etc.
However, I'm having an issue I didn't have before. Our application has objects that may be added to the map or moved at any time, plus objects that are procedurally created, which get recreated when a different LOD is loaded on the map.
The main problem I'm seeing is this: while zooming in/out of the map (using the CameraController from the samples project), sometimes objects appear to move to a very different part of the map. I believe the issue stems from raycasting (placing an object) while the world tiles are updating. Perhaps the raycast hits somewhere, and I convert that Enginelocation to a Geometry location, but then the geometry moves and my object ends up at the wrong spot. I've tried moving my raycast to different times in the Unity loop (Update, FixedUpdate, LateUpdate, WaitForEndOfFrame, etc), but none of these changes has solved the problem.
Any thoughts on how to workaround this problem? Or a better approach to getting the ground position of a lat/lon altogether?
Hi Garret, so not sure how you were doing this before our final release without mesh colliders to place objects on the surface of the earth.
This is something that is certainly possible now, the best advice I can give you is to look at the routing or feature layer sample because we are doing exactly what you are trying to do in those samples to positions objects on the surface of the earth. https://github.com/Esri/arcgis-maps-sdk-unity-samples
In the previous version, I edited the source to add mesh colliders on the surface myself.
So aside from that, my code is largely the same now as it was. However, we are placing objects with greater frequency and less predictability than a mouse click, and if the user happens to be zooming in or out when the object is placed, sometimes it ends up in the wrong spot. Sometimes the wrong spot is floating in the sky above the expected location, and sometimes it seems to be a different lat/lon.
I believe I was able to reproduce this issue within ArcGISHitTestSample. See the attached image, raycast-above.PNG. I shift-clicked while scrolling, and the text ended up floating way up in the air (hard to tell the 3D position in a static image, but that's how it is). This doesn't occur every time you raycast while scrolling, but it happens frequently enough to be noticeable.
As I mentioned, I think this is related to the world tiles refreshing when the raycast occurs. The mesh colliders have not updated to where the world appears to be at the time of the raycast, or something along those lines.
The routing example is very relevant, as we have a features that works almost exactly like that - a line renderer with anchor points, and we dynamically raycast some amount of spaces in between to make the line contour the surface. In the previous version of ArcGIS, I added collision detection to these objects, and via OnTriggerEnter/Exit I knew the world geometry had changed, so I would redo the raycasting to perfectly align with the new elevation and avoid any part of the line clipping through terrain (this is basically our custom version of rebasing the line object).
It worked 100% in the previous version, but in the new one, the line often ends up in the wrong position after the rebase. See the other attached images - in line1.png, the line is where I placed it, roughly at the corners of the runways. In line2.png, after zooming out and rebasing, the line renderer ended up shifted. I can look at using the rebase method from the sample to see if it helps, but I suspect I'll end up with lines that clip through hills after zooming out (that's what I see if I zoom far out in the sample and increase the width of the line renderer). Plus, we still have other objects that get placed and land in the sky while zooming.
Sorry for the huge text dump. Hope it clarifies the issues we're seeing.
Sorry your response slipped under my radar.
So there are a lot of things going on here but I'll try to answer all of it.
First and foremost I think what you need to do is work thru either the routing sample or the feature layer sample in our repo. They are solving a lot of the problems you are mentioning so I think it would just be easiest to work thru those samples and try to understand what they are doing.
The image from the raycast sample looks fine to. We were intentionally placing the text in the air above the building using an offset.
As for the point not being in the right spot when you do the identify, is that we are dynamically loading content based on what you are looking on. If you try to do a raycast on a point that is not loaded there will be no content to do a raycast. Or more likely there is some data loaded but it is ultimately at a much lower level of detail than what the data appears to be when you get closer to it. The Feature Layer sample account for this by doing the raycast when you get to a point where the data would be loaded. The Geocoding sample also has a similar approach to this.
As for the rebasing issue you are mentioning. Line renders have all their points specified with a regular unity transform so what we are doing in the routing sample is every time we rebase we are manually updating all the points in the line renderer so it stays in the same world position.
The issues you have brought up ultimately are solvable in the current version of our SDK but we totally understand that the UX on this could be way better. We will be simplifying this functionality to get eleavtion in our next release but in the meantime the raycast approach is a good solution. I have also seen other users, use a 3rd party service to query the elevation for a specific point and then use that.
We will get a much quicker response to you the next time you respond, apologies about that again.
Thanks for the reply. I have taken a look through most of the samples already, but each one seems to fall short for our use case. As I mentioned before, the routing sample fails at scale, though it's works well up close. The method of rebasing is to offset each Unity-coordinates point by the amount the universe moved. This works until the LOD starts changing significantly on the map. The shape of the terrain has changed, but the shape of the route hasn't, so the line is prone to clipping through terrain. See images Routing 1, 2, and 3. Note that I manually scaled up the line width as I zoomed out. In our app, we automatically scale the line with distance from camera.
The Feature Layer sample actually seems to exhibit the exact problem I'm seeing. Sometimes when I jump to a stadium, it ends up floating in the air above it's location. See the Stadium image. It seems like maybe the stadium loaded in on the ground while the map was in a rebasing state (my best guess for this issue).
And back to the Raycast Sample, it's hard to tell in a static image, but the text isn't offset at the programmed amount. It's hundreds of feet in the air. I attached the hittest_correct and hittest_incorrect images to hopefully make this more clear.
For now, we have stuck with the Beta version because this functionality is working more consistently with our source code edits than in the Release version, though there are still some flaws. It seems like it would be very helpful if there were events or flags conveying the state of the world rebase, so we would know when the terrain is "ready" for an accurate raycast. That's just an idea off the top of my head without a real idea of how it's working behind the scenes, though.
As for querying the elevation, it seems like a cumbersome way to handle it with the amount of objects/lines that may be on screen at any given time.
If there is a more built-in elevation solution coming in the future, it sounds like the best option may be to wait until that gets released.