Mouse hover over tilemap kills the performance

IMPORTANT INFO:i am making a battleground style 2d sideview game that has a randomly generated destructable/minable tilemap using perlin noise alghoritm mixed with destructable renders(pngs). i can generate the map, put prefabs as important points randomly (arenas etc.), functional active physic, destroy the map and prefabs without almost any performance isues and so on. i am also new to the unity engine so excuse my simple mistakes. also my system is kinda old (gtx 1050 laptop) but the game i am making is not that performance hungry with being in a 2d voxel style and not that many physic actions

PROBLEM: in short in the play mode when i only hover over the tilemap with my cursor my performance plumits. normally i get steady 60 fps while doing any action (destroying/mining the tile map without hovering over the tilemap) but this is the only action that kills my performance. here are some other infos:

i use unity’s old input system, my randomly generated tilemap is 2000 by 1200 tiles (each tile is 1by1 pixel btw [also i realize that my map is really big but apart from hovering over it i dont have any performance isues with it being that big]), player is active physic so it has physic animation not static

here are some screenshots and profiler info for the performance info

this fist image is when i hover over the tile map with my mouse cursor

these are the profiler’s main performance usage when mouse hover:
Monobehaviour.OnMouse_
40.90ms

SendMouseEvents.DoSendMouseEvents() [Invoke]
40.90ms

Physics2D.GetRayIntersection
40.85ms

Physics2D.GetRayIntersectionAll
40.85ms

First, you should use Deep Profiling, it will go much deeper in the stack and may help pinpoint the problem.

I think that your problem may come from the number of GameObjects.
The raycast has to be checked against several millions GameObjects, which is probably the reason why it takes so much time.
Also, the UI isn’t well optimized so it may explain why you have a problem only when hovering.

Maybe you can try to remove the Unity events system (or untick the ‘raycast target’ of your tiles) and make your own raycast.
And in fact, I wouldn’t use a raycast, but the mouse coordinates and the tiles coordinates.
It should be fairly easy to know over which tile the mouse is just by looking at the coordinates, and it should be incredibly fast.

thank you for you response and great info. i already use cordinate based system with tile stuff. and i tried to disable the event system but still the same isue.

also you said to untick “raycast target” but there is no option in my tiles or tilemap. that option is there for only my ui elements. even i untick that from a few ui elements i have still the same isue. and my UI has total of 5-6 image elements and thats it. they have no important functinality.

you were talking about not using raycast. how can i disable it? isnt this done in the background by unity? none of my code uses raycasting and even i disable every code in my game still the same isue.

extra note: i use old input system and from some of the discusions that system maybe causes this isue but i am not sure.

I never used 2D in Unity, but it should work like 3D, so removing the colliders from the tiles should do it.
Your profiling indicates that a Raycast2D took a lot of time, removing the colliders should help a lot.

Also, there may be other things to optimize, you should also use deep profiling and look at the ‘Raw Hierarchy’, that will tell you exactly which methods are consuming CPU.

but player will just fall if there is no colliders. tilemap already has tilemapcollider2d for the collisions. each tile dont have colliders spesificly

Well, look in the ‘Raw Hierachy’ of the profiler who is calling the raycast, maybe you can find a way to avoid calling it.

it seems that main call is coming from the player loop and gradually go to the raycast. is there a way to check what is calling this sendMouseEvent?

There are probably several ways, each with their own problems.
If you can find some input-events component you may try to remove it.
As I said before, maybe removing the colliders would help, even if it means finding another way to avoid the player not to fall.

There’s this thread which may help you:

Also, have you tried in standalone instead of within the editor?
Maybe there’s no performance problem in standalone, who knows, luck does happen sometimes.

AFAIK this is called from the legacy input system; it’s not controlled via physics. It performs 2D and 3D raycast “into” the screen and for 2D it uses Physics2D.GetRayIntersectionNonAlloc which is a pseudo-3D call (2D physics obviously doesn’t have depth) which I wrote to allow these 3D-style raycasts.

You can see the code here: UnityCsReference/Modules/InputLegacy/MouseEvents.cs at 6500e74a5acecc1082419bc010ad7de273b87d2d ¡ Unity-Technologies/UnityCsReference ¡ GitHub

What is troubling is why it’s taking so long. You do have a crazy dense tilemap from the sound os it and it’s unclear what kind of collider shapes are on there but a call should not take that long unless the shapes are so close, the physics broadphase tree is taking an age to return results but 40ms+ is crazy.

I would suggest you use the above call yourself as a test; you can use Camera.ScreenPointToRay passing in the mouse position then passing the Ray into the above query to see if it takes a long time.

Looking at the input code, it should avoid any of this if the Camera.eventMask is zero so maybe you can try resetting that as a test.

I would say though that you should look at what’s going on in terms of the number of shapes. All that information is shown in the 2D physics profiler area. If the tilemap is not changing dynamically then I’d consider merging those shapes using a CompositeCollider2D but until you know what the issue is then its hard to be exact. Lots of shapes can take up a lot of memory too.

you are crazy to make this type of game and using the tilemaps and composite collider, i dont know how you dont have trouble everytime you destroy the terrain i would expect your pc to blow up when remaking the collider and setting tiles, good luck tho if its working so far

To be fair, the OP never said they used the CompositeCollider2D. It’s also why I said he’d be better using the CompositeCollieder2D if the tiles are not changing in which case it’d take far less memory because it’d producing fewer shapes and would be faster on start-up.

That said, physics isn’t a pixel perfect thing and I’m very curious on what the actual scale of each tiles is here in world-units.

it does look like a worms armageddon kind of deal, with 1 pixel of terrain = 1 tile

Normally i was doing tilemapcollider2d for the colliders. But even tho mining is really smooth mouse hove and ray cast was an isue. That was the point i was stuck. But now i am trying a new aproach with all of the replies.

Now i am using composite collider but not as a single tile map( even mining a single tile takes forever and i see that every tile remove is teying to change the 1 big collider). I am spliting the tile map into multiple tilemaps but on the eye it all seem as a 1 big tile map. So now when you nreak a tile it only changes that spesific section rather then changing the whole section.

I am working on this aproach right now and even after some split test all of my performance isues and cons are gone. Roght now i am trying to make the code work with structure placer code (randomized houses, arenas etc.)

This is the final and best aproach after all of the replies but i would love to hear some diffrent aproaches as well which i can try

Extra note: i can also add your sugestion into this aproach for the most efficent aproach but i can try it after the tilemap split part

Also some things i found out with colliders: I AM REALLY STUPID TO START THIS WITH TILEMAPCOLLIDERS AND 1 GIANT TILEMAP (i guess thats just me being a beginer). But besides that tilemap collider is great for breakable tilemap but when it comes to generating and casting it is really bad. Its kinda opposite for the 1 tilemap composite collider aproach. Generation is fast but because its a 1 big collider game doesnt really like it when i try to breakt the tile map. So i think splited tilemap with composite collider will be the best aproach but idk i will inform you guys when its all done

Also another question. For this kind of project would it be better to transform into new input system for the performance vise? Or would the performance be as same as the legacy (old) input system

Your only concern with input system choice is its functionality. It shouldn’t even make your top 100 as far as performance concerns go.

1 Like