Asteroid Field 4.17
Time ago i was looking for how to use Instanced Static Mesh for an asteroid field and found this tutorial on youtube from Tech Art Aid [MENTION=5535]Oskar Świerad[/MENTION]
the problem with ISM/HISM is that add rotation to a every single instance have an expensive cost in terms of performance.
In simple words, check for instances in a “visible” range, destroy and replace these instances with a Blueprint actor that simulate physics to add rotation.
Basically what i technically do is get all the instances that are inside a sphere that have center in the player camera and radius as the “visible” range you want, after that i “filter” all these instances with a dot product and if the result (in degrees) is inside the FOV value (in degrees) of the camera they will go to the second “filter” pass, i throw a linetrace between the camera and the instances, if i hit the player pawn i “discard” the instance from to be replaced, if i don’t hit something means the instance is “visible” and i remove and replace it with an actor blueprint that have the same Static Mesh in the same position and rotation with simulate physics active and an initial torque force to start the rotation.
Here some pictures with debug traces activated (FPS are very low because all the debug lines and spheres).
Red sphere and lines are the “discarded” instances from be removed and replaced with BP actor.
Blue sphere and lines are the instances that are removed and replaced with BP actors.
Green lines are the trace that hits the player pawn ship and “discard” instances to be removed and replaced.
Big purple sphere is the GetInstancesOverlappingSphere sphere (yep, is a sphere), sadly have the same color of asteroids in wireframe mode, i hope you can easily see it from the pictures (sorry for it).
Basically the problems of my solution are performance, the function have a couple of for loop and it’s called every tick from pawn with an event dispatchers because you frequently need to know the camera position, after some debug test with frontend profiler seems the GetInstancesOverlappingSphere call is very expensive (something like 2ms) and in total the SwapAsteroids function take between 2ms to 5ms to be executed.
That means you don’t have to exxagerate with the “view” distance or you will encounter a massive framerate drop but if you manage with range and distance between asteroid values you can achieve a good effect with a stable framerate (over 150fps on my system).
Could be very nice have a funtion like GetInstancesOverlappingCone or Hemisphere to cut off the initial area we are looking for.
Here how you can use BP AsteroidField SwapAsteroids function
Create an event dispatcher in the player pawn and call it with FOV and camera transform
Bind it in at BeginPlay in the AsteroidField blueprint
BP_AsteroidField details panel (sorry if variables naming is not the best)
OffsetX: distance on the X axis between asteroids
OffsetDeviationX: use it to add some random to the distance value (in default settings is at 100 that means distance will be between 900 and 1100 units).
OffsetY: distance on the Y axis between asteroids
OffsetDeviationY: use it to add some random to the distance value (in default settings is at 100 that means distance will be between 900 and 1100 units).
OffsetZ: position on Z axis, will be a random value between -OffsetZ and +OffsetZ
SwapRange: basically is the radius of “big sphere”, how far you will go to check instances.
OffsetFOV (in degrees): this value is added to the FOV on check if instances are in a visible range, you need it because line traces are from camera to the center of the asteroid and could be happen that you can see a portion of the asteroid but is not “swapped” because his center is out from the desired view angle.
ShowDebugHUD: as variable name said
ShowDebugTraces: as above, enable it will cause an important framedrop
MaxInstancesX: how many asteroid instaces on X axis the field will have
MaxInstancesY: how many asteroid instaces on Y axis the field will have
AsteroidMesh: the static mesh for both instanced mesh and blueprint actor
MinAsteroidScale: the minimum value of how much the mesh will be randomly scaled
MaxAsteroidScale: the maximum value of how much the mesh will be randomly scaled
AccelChange: is a torque option, if you disable it you will need a very big torque value to start rotate your asteroid
MinRotationTorque: the minimum value for random torque force applied to the asteroid
MinRotationTorque: the maximum value for random torque force applied to the asteroid
OverrideMass: override the mass of the static mesh
MassInKg: custom mass value (used if OverrideMass is set to true)
StartCullInstance: distance from camera at which each instance begins to fade out
EndCullInstance: distance from camera at which each instance completely fades out