- Home /
Issue with Raycast Detection in Editor
Hi everyone!
I have an issue with raycasting that makes absolutely no sense to me. I'm in the process of making a level editor that's going to allow me to place "spaces" (squares, tiles...) that the player can walk on. Additionally, I want to allow placement of coins on top of some of these tiles. I have it set up to where you can click in the scene view in the editor to place tiles / coins. Then I have it set up to where if it's in delete mode, I have it cast a ray at the position clicked and delete the tile or coin it hits.
The issue I'm having is that it won't ever let me delete the last coin I place. It lets me delete tiles normally. If I place another tile, it lets me delete the coin and the tile. If I place another coin, I can delete the original coin but then can't delete the last coin I placed. It only goes wrong with the last coin I place.
This is relatively minor, because I can just place a tile and delete both, but I feel I should be able to fix this and I'm not sure what is going wrong.
Edit: Forgot to mention that the reason it's not deleting the last one I place seems to be because the ray being cast doesn't hit the last coin. It hits the other coins, but not the last one I place. And that makes no sense to me.
Here's the relevant code I have so far for the placement of tiles:
// load the correct prefab and create an instance of it
GameObject space = Resources.LoadAssetAtPath(pathString, typeof(GameObject)) as GameObject;
GameObject spaceInstance = PrefabUtility.InstantiatePrefab(space) as GameObject;
spaceInstance.name = current;
spaceInstance.transform.parent = tempParent.transform;
// set its position to where we click
Vector2 mousePos = Event.current.mousePosition;
mousePos.y = Camera.current.pixelHeight - mousePos.y;
Vector3 position = Camera.current.ScreenToWorldPoint(mousePos);
position.x = Mathf.Round(position.x);
position.y = Mathf.Round(position.y);
if (space.name == "Coin")
position.z = -0.5f;
else
position.z = 0;
spaceInstance.transform.position = position;
EditorUtility.SetDirty(spaceInstance);
And for deleting:
Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray.origin, ray.direction, out hit, Mathf.Infinity))
DestroyImmediate(hit.collider.gameObject);
Help would be appreciated!
Answer by RyanZimmerman87 · Mar 21, 2014 at 01:47 AM
Sounds like a pretty cool project you are working on but a lot of your specific syntax I have never even used.
For example all this stuff:
GameObject space = Resources.LoadAssetAtPath(pathString, typeof(GameObject)) as GameObject;
GameObject spaceInstance = PrefabUtility.InstantiatePrefab(space) as GameObject;
I would just create two public GameObject variables to store your coin and tile prefabs. Then you could just instantiate a copy of each GameObject as a clone every time you place a new one.
I'm not sure if that's not possible with the Editor stuff you are trying to do. I'm just trying to simplify your problem if at all possible based on my experience.
Also not sure why you are using:
Vector3 position = Camera.current.ScreenToWorldPoint(mousePos);
to place your objects. But you are using:
Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
for your deletion.
Not saying your way is wrong, I have no idea since I've never tried a lot of this stuff. But I've always used something like this and I've never had problems selecting GameObjects:
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
That way draws a ray from your camera position to the object you are selecting. I think I just don't really understand your project though if you are trying to do this all with GUI stuff instead of Camera stuff for the rays and event selection.
And since you are using the Editor it might be perfectly fine but you might want to just try:
Destroy();
Instead of:
DestroyImmediate();
It sounds like it could cause a lot of problems although they do say it should be used with Editor stuff, but I'd give it a try using Destroy() if it works. Here's the documentation:
"Destroys the object obj immediately. You are strongly recommended to use Destroy instead.
This function should only be used when writing editor code since the delayed destruction will never be invoked in edit mode. In game code you should use Object.Destroy instead. Destroy is always delayed (but executed within the same frame). Use this function with care since it can destroy assets permanently! Also note that you should never iterate through arrays and destroy the elements you are iterating over. This will cause serious problems (as a general programming practice, not just in Unity)."
Not sure if any of that will help you. I'm kind of just guessing since I haven't used pretty much any of that stuff you are doing.
The last coin not deleting is really weird though it might just be some tiny error with your logic, you may wanna try using the public GameObjects for your tile and coin prefabs instead of the asset stuff. But once again I don't know if that's not possible in the Editor which would explain why your code seems strange to me compared to everything I've done so far.
Assuming you've tried some debugging text to show what you are selecting maybe you are hitting some other object before you hit the last coin? Also double check the name and variables of all your coins maybe the problem coin is somehow different?
Also not sure what kind of logic you are using to set the pathString variable?
Thanks for your answer! For the public objects, I think the only way to do this would be to have another object in the scene to put the references in then use some kind of GameObject.FindWithTag or GameObject.Find to get a reference to it. Because an editor script is not instantiated in the scene and so cannot have inspector-assigned data (to my knowledge...)
The thing is, though, that it's hitting all my objects and deleting them just fine (not sure if the Input class can be used in Editor mode, either. I'll have to check on that again...) and it's placing them just fine. The coins are cloned the same way from the prefab, and so don't have any differences whatsoever. That's what makes it so weird. It wouldn't be objects in the way of it, because I click many, many times and it never gets deleted. And besides, printing out what's being hit by the ray shows nothing at all. It doesn't even detect a hit when I click on the coin.
To set the path string, I have buttons set up. Each button is associated with a tile type or item type (such as coins). When you press on a tile button in the scene view GUI, it sets the path string based on the button you pressed.
Hmm I just read over this whole issue again, and I'm struggling to come up with any good solutions.
So do you always have to place a tile first then coin or can you place any amount of tiles and coins in any locations?
Does this problem still occur if you just place one coin and no tiles?
What if you place like 5 coins would 4 of them work just not the last one?
It's a very strange problem but I'm not sure if I fully understand the issue in an isolated fashion. It seems like it could be several different things that might cause it.
What resolution are you testing this in, you are using game view not scene view right? One possibility is that the screen size is not quite matching up visually with the world so maybe your rays aren't even hitting that coin. That wouldn't really make sense though unless it was just certain areas where you couldn't hit the coin not just the last coin being the problem.
You may want to set up some debug linecast to see what's happening with that ray.
Also you could double check for any conditions with your logic maybe for some reason your logic won't allow you to select that coin?
$$anonymous$$inda just guessing here, that's a weird problem maybe a screenshot or diagram of the problem coin could help.
I can place any amount of tiles and coins. And this issue only happens with coins.
If I place five coins, the first four can be deleted but the last can't. And it doesn't work if I place only one, either.
I'm using scene view for this. I put the editor in the scene view, and click in the scene view to make the levels. (I plan to make a player version so players can make their own levels in runtime, too. But I haven't built that yet, so I can't speak for it).
It would be weird if the ray works as it should for all tiles and coins except the last coin placed... what would cause the ray to stop working properly? I did a line cast and the ray is at the right position.
Basically I look for a click event, and if a click event happens it checks the mode. If it's "destroy" mode, then it literally only runs that deletion code I posted above. And I'm not sure what in those four lines could be messing it up.
It seems like somehow it won't let you delete the last coin because it is somehow relying on there always being at least one coin.
Some of the DestroyImmediate documentation made it sound like you could permanently delete a prefab with your project if used incorrectly? $$anonymous$$aybe it's something related to that but still it makes no sense why it's only coins but not tiles.
Are there any differences between the coins and tiles? Like maybe the coin has some kind of static variable for it's movement or the script that won't allow you to delete it from the scene once it's placed?
I would probably try placing a coin in the scene and use that for cloning new coins ins$$anonymous$$d of grabbing it from the asset path.
And just check all the coin and tile variables for their colliders, scripts, but most importantly static settings.
It's also possible that some kind of logic in your code will only delete coins if they aren't the last one. But from the code you posted it looks like all it needs is a collider.hit.
One other thing you might wanna check is that maybe if you have one script which is instantiating all this stuff perhaps it's losing some data somehow for the last coin? Or whatever script tries to delete the last coin can for some reason not access the data for that object?
That's all just a bunch of guessing. It could very well be just a Unity bug for all I know, I'm not sure if the Editor is very well designed to be able to do that kind a stuff, but it sounds pretty cool so it probably should be. Have you tried just doing this in the real build ins$$anonymous$$d of the Editor? If you want to let players save their own levels you will need to add that eventually right?
$$anonymous$$inda surprised nobody else has attempted to help since I'm sure there's some guys who have done some editor work sorta similar to what you are trying, I'm just guessing right now.
Oh a few last ideas you could try using:
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
It sounds like what you are doing draws from the camera too but might be worth a try if it works in editor mode, it's always worked for me.
Also you could try using a value for the ray length ins$$anonymous$$d of $$anonymous$$athf.infinity, just to eli$$anonymous$$ate the possibility of that causing some kind of Unity bug.
And do you only have coins and tiles in the scene? You might want to try to verify that there are no other objects in the scene that are somehow intercepting that last coin's raycast.
One final desperation solution could just be to have a count of how many coins are in the scene, if it's just one coin you could create an extra coin somewhere offscreen that the user wouldn't know about before you delete the one you are trying to. That's not really a solution to the bug or problem but at least you could maybe go ahead with the project for now and try to just ignore it even though it's super annoying.
Answer by UVmatician · Jul 04, 2018 at 01:30 PM
Hey, I know this is an old post. But I had a similar issue and I think I found the answer.
I'm using Unity 2018.1.6f.1 .
It seems that when you instantiate a prefab in the scene from an editor script, it doesn't register that object's colliders with the physics system right away. So Raycasts don't work on the newly placed object.
I found I could force it to register the collider right away by disabling and then reenabling the collider in the script right after creating it.
GameObject newObject = ((GameObject)PrefabUtility.InstantiatePrefab(newObjectPrefab));
Collider coll = newObject.GetComponent<Collider>();
coll.enabled = false;
coll.enabled = true;
Answer by Zaddo · Jul 03, 2021 at 02:22 AM
Yes this is an old post... This situation cost me a lot of time and I think it is worth necroing if this helps someone else with the same issue.
Use: Physics.SyncTransforms();
Your answer
![](https://koobas.hobune.stream/wayback/20220613140707im_/https://answers.unity.com/themes/thub/images/avi.jpg)