Has anyone tried making semi-realistic tornados in Unity?

I’ve worked on games that run entire atmospheric simulations in space, and understand how complex and complicated they can get especially on large-scale maps, So I decided to cheat it a little and create a radius that just pulls objects towards it and add a rotation to it. It was based on this script Make Tornado Physics in Unity | Sharp Coder Blog.

While that works for objects I wanted to extend it to work with Unity terrain mainly their terrain details but after looking at the Unity API for (TerrainData.GetDetailLayer and TerrainData.SetDetailLayer) I really didn’t see how to edit the layer.

I found an old script that would allow editing of the heightmap data to create in-game editors for maps and attempted to covert it to instead remove terrain details from within a specified radius but I still am having no luck I’ll post the brush section of the script below. Just reaching out to see if anyone can help me out as I’ve gone wrong somewhere and have spent a good week on this one function.

``````void PaintCircle()
{
float x;
float z;
float detailX;
float detailZ;
Vector2 calc;
{
{
// for a circle, calcualate a relative Vector2
calc = new Vector2(x, z);
// check if the magnitude is within the circle radius
{
// is within circle, paint height
detailX = rayHitPoint.x + x;
detailZ = rayHitPoint.z + z;
// check if heightX and Z is within the heightmapData array size
if (detailX >= 0 && detailX < DetailMapWidth && detailZ >= 0 && detailZ < DetailMapHeight)
{
for (int i = 0; i < terrain.terrainData.detailPrototypes.Length; i++) //The List its accessing is just all the detalis layers stored in the terrain data.
{

//Get the Detail Layer
var map = terrain.terrainData.GetDetailLayer(0, 0, (int)detailX, (int)detailZ, i);
//Remove the details in the selected area
map[(int)x, (int)z] = 0;
//Apply it back to terrain
terrain.terrainData.SetDetailLayer(0, 0, i, map);
}
// update heightmapData array(This was chaning hightmap)
//DetailMap[detailZ, detailX] = detailY;
}
}
}
}
// apply new heights to terrainData
//    terrainData.SetHeights(0, 0, DetailMap);
}
``````

If anyone needs the entire script I can post it just didn’t want to overcrowd the post

That’s an interesting idea, the effect itself should be pretty straightforward to make because you can just create a fancy particle system or shader to take care of the graphics. If I were to do it I would take advantage of the rigidbody system and I would have a look at the physics behind an actual tornado in real life and how it works. Tornados seem to suck stuff in and spin them around so what I would do is potentially make the rigibodies the child of the tornado’s gameobject and have it rotate pretty fast and you could have the origin in the centre somewhere and have the rigidbodies go towards the origin then add force on the Y axis when they reach it, you could even be extra fancy and put a collider in the centre.

There might be a more accurate mathematical solution to this but that’s how I’d look at the physics side of things. You don’t necessarily need to rely on direct maths though sometimes to achieve the effect you want as long as you understand what it is you’re messing with when it comes to rigidbodies and general physics components.

If you want to get really anal about this though and go the simulation route, there is maths out there by scientists on this topic, but you’ll need to know how to convert their algebra to C# which is something I wish I had more knowledge on.

https://www.sciencedirect.com/science/article/pii/S1674987111000247

Thanks although I can’t take all the credit. I do have something along the lines of what you are talking about it affects game objects/anything tagged as interactable and has a rigid body component. And I created a VFX particle system to create the cloud effect that gets darker depending on the overall density of the particles.

The part that’s got me really stuck is removing the grass when the tornado passes over the top. While this is an only small detail I feel it plays a big part in the overall damage a tornado can cause. I wrote the small script above that should remove details within the tornado’s radius of effect but I’m not sure if I’m doing it correctly. I get the height map to write to what I think is the correct area of the age and then set it back. Obviously, I haven’t done it right though as nothing seems to change in-game. It calls the above function every second to help as it is pretty expensive.

As the tornado’s overall structure won’t warp that much you could have a collider at the top to keep a track of the grass, alternatively maybe use grass particles, you could even use a grass mesh on the particles and just have them fade over time.

Ah Sorry I think there was a misunderstanding there, It was pretty late when I wrote the original post. But I’ll do my best to clarify.

Im trying to remove grass from the terrain underneath the tornado it’s part of the terrain data of the terrain. The function terrainData.GetDetailLayer outputs a 2D array of this data. I’m trying to select a small area edit it to a value of zero (which changes the density of the grass to zero) then save it back to the terrain using terrainData.SetDetailLayer.

There’s not much in the way of editing small sections of terrain data that I can find in the unity API. The function I posted on the first post was an attempt at doing it but It’s not working.

I was wondering if anyone knows how to edit terrain data/create an erase brush for runtime editing of terrain. (The brush is the tornado)

Sorry for the confusion but thanks for the ideas

I don’t specifically know for the details, but I have some intel that might help you figure it out.

This script deforms terrain based on a world position of a grenade / bomb, and changes the splatmap too.

It’s possible the coordinate system for the detail you need is calculated the same way.

MakeGeo is presently hosted at these locations:

https://bitbucket.org/kurtdekker/makegeo

I’d still potentially use a collider for that but just have it at the bottom, it should let you keep track of the grass objects that way, alternatively you could program an overlap sphere of some sort.

I think that’s the issue here: these grass objects (AFAIK) are not really GameObjects in the scene but appear as a function of the terrain detail meshes, so I don’t believe they are considered for collisions.

As OP notes:

I could be wrong but I don’t think those little bits of mesh exist in the physics space, so you would need to locate them for removal by some coordinate transform from world coordinates into the terrain data coordinates, which the terrain damager code above does as well, smooshing the terrain down where you want it.

1 Like

Yep Exactly Even terrain trees are part of the terrain, The details and height are both saved as heightmaps that can be accessed through 2D arrays. each detail prototype (Each type of grass or flower) is added as its own layer.

I haven’t had the chance to take an in-depth look at the GitHub provided but am taking a look later today, I did find a few similarities between that and what I had so it looks like I’m on the right track. When I do get it working I’ll share it here so that if anyone in the future ends up hitting the same issues I’m facing it’ll help them out.

Okay It’s working “partially”. There are a few issues with my current script.

1. The terrain must be set to a position of 0,0,0 to work so having multiple terrains set up as I do will require some additional math to work out the delta of the heightmap position to world position. It should be relatively easy.

2. The harder more complicated part is that I’m using Gaia’s Flora system that replaces the details system that could have made this a little all for nothing… But at least I’ve found a way to do this and it can be easily applied back to heightmaps for runtime world editing.

Once I fix the first issue I’ll post the solution here for anyone that might need it in the future.

1 Like