Func Forcefields: Difference between revisions
No edit summary |
|||
(13 intermediate revisions by 9 users not shown) | |||
Line 1: | Line 1: | ||
= Using | For a more recent and comprehensive introduction to this subject, see [[Force Fields]]. The earlier page here still provides useful insights, particularly about: | ||
* behavior of AI and cadavers in rivers | |||
* defining uniform on-axis/off-axis forces | |||
* affects on performance | |||
{{Original_Reference|Ishtvan|5502}} | |||
= Using func_forcefields = | |||
The basic documentation is there in the usage tab in the editor, if you place a func_forcefield and look at it. I'm just going to explain some of the more subtle stuff so that whoever creates this map can set it up. | The basic documentation is there in the usage tab in the editor, if you place a func_forcefield and look at it. I'm just going to explain some of the more subtle stuff so that whoever creates this map can set it up. | ||
First of all, a func_forcefield is a brush. Stuff inside that brush is | First of all, a func_forcefield is a brush. Stuff inside that brush is affected, stuff outside is not. You can resize and reshape it however you want. | ||
It will not work correctly if you texture the brush with common/nodraw, but you can use common/caulk. | |||
Force fields have spawnargs for whether they should apply their push as a force, an impulse, or a velocity. These are set with spawnargs applyForce, applyImpulse, and applyVelocity. A force field may only apply one of those. Set the one you want to "1". | Force fields have spawnargs for whether they should apply their push as a force, an impulse, or a velocity. These are set with spawnargs applyForce, applyImpulse, and applyVelocity. A force field may only apply one of those. Set the one you want to "1". | ||
It turns out that applyForce doesn't work on AI, and applyVelocity doesn't feel right because your velocity suddenly jumps up, which is unrealistic (that might be okay for some applications). For stuff like river current or wind, I'm recommending applyImpulse, by setting the following: | It turns out that '''applyForce''' doesn't work on AI, and '''applyVelocity''' doesn't feel right because your velocity suddenly jumps up, which is unrealistic (that might be okay for some applications). For stuff like river current or wind, I'm recommending '''applyImpulse''', by setting the following: | ||
"applyImpulse" "1" | "applyImpulse" "1" | ||
Line 13: | Line 22: | ||
A forcefield has a few different modes of directing the force. It can explode out from a point, implode toward a point (both of these things limited in distance by whether objects are actually within the force field brush). Or it can be uniform (force is directed the same within the whole brush). For river current, we want uniform. | A forcefield has a few different modes of directing the force. It can explode out from a point, implode toward a point (both of these things limited in distance by whether objects are actually within the force field brush). Or it can be uniform (force is directed the same within the whole brush). For river current, we want uniform. | ||
= The "uniform" spawnarg = | |||
The direction and magnitude of your force field can be set in the "uniform" spawnarg, which is a space-delimited 3d vector. Decide which directions you want your force field to go in on the map. If you're confused about which direction is which, changing views helped me see it, because the views are labeled YZ for example, so I instantly know which direction is the Y direction by looking at the YZ view. | The direction and magnitude of your force field can be set in the "uniform" spawnarg, which is a space-delimited 3d vector. Decide which directions you want your force field to go in on the map. If you're confused about which direction is which, changing views helped me see it, because the views are labeled YZ for example, so I instantly know which direction is the Y direction by looking at the YZ view. | ||
Once you know, you can put in the force field. If you want a uniform 2d field in one 2d direction, use this equation: Figure out the angle off of the x axis for your direction. For example, y is 90, -y is -90, etc. | Once you know, you can put in the force field. If you want a uniform 2d field in one 2d direction, use this equation: Figure out the angle off of the x axis for your direction. For example, y is 90, -y is -90, etc. | ||
= In-plane force field (no vertical) = | == In-plane force field (no vertical) == | ||
uniform[x] = Mag * cos( theta ) | uniform[x] = Mag * cos( theta ) | ||
uniform[y] = Mag * sin( theta ) | uniform[y] = Mag * sin( theta ) | ||
uniform[z] = 0 | uniform[z] = 0 | ||
Where Mag is the desired magnitude of your force. | Where Mag is the desired magnitude of your force. | ||
Line 28: | Line 37: | ||
If you want a uniform force in 3d, you also have to figure out roughly the elevation angle off of the XY plane (I'm calling it phi), and use the spherical coordinates formula: | If you want a uniform force in 3d, you also have to figure out roughly the elevation angle off of the XY plane (I'm calling it phi), and use the spherical coordinates formula: | ||
= Out of plane force field (vertical component to the force) = | == Out of plane force field (vertical component to the force) == | ||
uniform[x] = Mag * cos(theta) cos( phi ) | uniform[x] = Mag * cos(theta) cos( phi ) | ||
uniform[y] = Mag * sin(theta) cos( phi ) | uniform[y] = Mag * sin(theta) cos( phi ) | ||
uniform | uniform[z] = Mag * sin( phi ) | ||
Some people define phi as the angle deviation from straight up instead of an elevation from the horizon, in that case interchange cos(phi) and sin(phi). | Some people define phi as the angle deviation from straight up instead of an elevation from the horizon, in that case interchange cos(phi) and sin(phi). | ||
Line 42: | Line 50: | ||
= Other spawnargs of interest = | = Other spawnargs of interest = | ||
Again these are documented in the usage tabs in the editor | Again these are documented in the usage tabs in the editor. | ||
== start_on == | |||
Make sure that if you want your force field to always be active, you set: | |||
"start_on" "1" | "start_on" "1" | ||
Otherwise, you can trigger it to toggle whether it's active. | Otherwise, you can trigger it to toggle whether it's active. | ||
== scale_impulse == | |||
Starting with TDM 1.08, a 'scale_impulse' spawnarg has been added to vary the amount of force in an impulse forcefield. | |||
"scale_impulse" "1" | |||
This linearly scales down the applied force for objects with less mass than the player. | |||
This was introduced so that larger forces--necessary to move the player along--would not cause smaller objects to react in an unrealistic manner. In the interest of not breaking existing missions that use this type of forcefield, the 'scale_impulse' spawnarg was introduced for mappers who want to use the scaled force. | |||
= Performance = | = Performance = | ||
Because a force field is constantly activating physics objects and evaluating their physics, it could potentially drag down performance. The following are some tips to help keep performance reasonable: | Because a force field is constantly activating physics objects and evaluating their physics, it could potentially drag down performance. The following are some tips to help keep performance reasonable: | ||
* The more physical objects within the forcefield, the worse the performance. | |||
* If you can, place triggers to trigger the force field on or off based on whether the player is entering or leaving the area it's in. This may be difficult in large outdoor maps with large rivers, since you'd have to place huge triggers and those themselves have some impact on performance. In the case of one huge river in a map, it might be better to just write a script that triggers the forcefield or not based on distance to the line of the river. | |||
* Make sure the field does not pile up objects somewhere! As long as the field pushes objects out of it, they'll exit the field by themselves and you won't have to worry much about performance. However, if the field goes right up to a wall, and pushes objects against that wall, the objects will not come to rest, they'll keep getting that impulse and keep getting smacked against the wall, using up CPU resources. <br> I'd recommend putting some dropoff or a brush that destroys objects or something at the end of your force field. Keep in mind that even if there is a small space, objects could pile up in that space and the next object would hit that object and still be stuck in the field, so you really have to watch out for this. | |||
* Creative spawning/destroying or teleporting objects: How do you get a large river with random debris floating down it, when eventually all the debris will get pushed to the end? Well, you could do some scripting, spawn objects at one end of the river, and delete objects at the other end. Or, you could set up a brush to teleport the objects back to the start of the river and keep the same objects. A Prey-style portal would be ideal here, but those don't work in D3 without a lot of SDK modification. | |||
= Known bug: AFs in water = | |||
If you try to set up a river and there's a dead body in it, it will probably take off like a bat out of hell, because there's currently a bug/hack in the water physics code that reduces masses of Articulated Figures in water. This makes impulses applied on AFs in water send them flying. | |||
= See also = | |||
[[Force Fields]] | |||
[[Objects_Floating_in_Water]] | |||
{{editing}} | |||
{{water}} | |||
[[Category:AI]] |
Latest revision as of 23:15, 14 December 2021
For a more recent and comprehensive introduction to this subject, see Force Fields. The earlier page here still provides useful insights, particularly about:
- behavior of AI and cadavers in rivers
- defining uniform on-axis/off-axis forces
- affects on performance
Originally written by Ishtvan on http://forums.thedarkmod.com/topic/5502
Using func_forcefields
The basic documentation is there in the usage tab in the editor, if you place a func_forcefield and look at it. I'm just going to explain some of the more subtle stuff so that whoever creates this map can set it up.
First of all, a func_forcefield is a brush. Stuff inside that brush is affected, stuff outside is not. You can resize and reshape it however you want.
It will not work correctly if you texture the brush with common/nodraw, but you can use common/caulk.
Force fields have spawnargs for whether they should apply their push as a force, an impulse, or a velocity. These are set with spawnargs applyForce, applyImpulse, and applyVelocity. A force field may only apply one of those. Set the one you want to "1".
It turns out that applyForce doesn't work on AI, and applyVelocity doesn't feel right because your velocity suddenly jumps up, which is unrealistic (that might be okay for some applications). For stuff like river current or wind, I'm recommending applyImpulse, by setting the following:
"applyImpulse" "1"
A forcefield has a few different modes of directing the force. It can explode out from a point, implode toward a point (both of these things limited in distance by whether objects are actually within the force field brush). Or it can be uniform (force is directed the same within the whole brush). For river current, we want uniform.
The "uniform" spawnarg
The direction and magnitude of your force field can be set in the "uniform" spawnarg, which is a space-delimited 3d vector. Decide which directions you want your force field to go in on the map. If you're confused about which direction is which, changing views helped me see it, because the views are labeled YZ for example, so I instantly know which direction is the Y direction by looking at the YZ view.
Once you know, you can put in the force field. If you want a uniform 2d field in one 2d direction, use this equation: Figure out the angle off of the x axis for your direction. For example, y is 90, -y is -90, etc.
In-plane force field (no vertical)
uniform[x] = Mag * cos( theta ) uniform[y] = Mag * sin( theta ) uniform[z] = 0
Where Mag is the desired magnitude of your force.
If you want a uniform force in 3d, you also have to figure out roughly the elevation angle off of the XY plane (I'm calling it phi), and use the spherical coordinates formula:
Out of plane force field (vertical component to the force)
uniform[x] = Mag * cos(theta) cos( phi ) uniform[y] = Mag * sin(theta) cos( phi ) uniform[z] = Mag * sin( phi )
Some people define phi as the angle deviation from straight up instead of an elevation from the horizon, in that case interchange cos(phi) and sin(phi).
Finally, you are ready to set your "uniform" spawnarg with your vector direction:
"uniform" "<x> <y> <z>"
Other spawnargs of interest
Again these are documented in the usage tabs in the editor.
start_on
Make sure that if you want your force field to always be active, you set:
"start_on" "1"
Otherwise, you can trigger it to toggle whether it's active.
scale_impulse
Starting with TDM 1.08, a 'scale_impulse' spawnarg has been added to vary the amount of force in an impulse forcefield.
"scale_impulse" "1"
This linearly scales down the applied force for objects with less mass than the player.
This was introduced so that larger forces--necessary to move the player along--would not cause smaller objects to react in an unrealistic manner. In the interest of not breaking existing missions that use this type of forcefield, the 'scale_impulse' spawnarg was introduced for mappers who want to use the scaled force.
Performance
Because a force field is constantly activating physics objects and evaluating their physics, it could potentially drag down performance. The following are some tips to help keep performance reasonable:
- The more physical objects within the forcefield, the worse the performance.
- If you can, place triggers to trigger the force field on or off based on whether the player is entering or leaving the area it's in. This may be difficult in large outdoor maps with large rivers, since you'd have to place huge triggers and those themselves have some impact on performance. In the case of one huge river in a map, it might be better to just write a script that triggers the forcefield or not based on distance to the line of the river.
- Make sure the field does not pile up objects somewhere! As long as the field pushes objects out of it, they'll exit the field by themselves and you won't have to worry much about performance. However, if the field goes right up to a wall, and pushes objects against that wall, the objects will not come to rest, they'll keep getting that impulse and keep getting smacked against the wall, using up CPU resources.
I'd recommend putting some dropoff or a brush that destroys objects or something at the end of your force field. Keep in mind that even if there is a small space, objects could pile up in that space and the next object would hit that object and still be stuck in the field, so you really have to watch out for this.
- Creative spawning/destroying or teleporting objects: How do you get a large river with random debris floating down it, when eventually all the debris will get pushed to the end? Well, you could do some scripting, spawn objects at one end of the river, and delete objects at the other end. Or, you could set up a brush to teleport the objects back to the start of the river and keep the same objects. A Prey-style portal would be ideal here, but those don't work in D3 without a lot of SDK modification.
Known bug: AFs in water
If you try to set up a river and there's a dead body in it, it will probably take off like a bat out of hell, because there's currently a bug/hack in the water physics code that reduces masses of Articulated Figures in water. This makes impulses applied on AFs in water send them flying.