Skip to content

Conversation

@Garanas
Copy link
Member

@Garanas Garanas commented Oct 28, 2025

Description of the proposed changes

Reduces the duration of splats made by projectiles. We introduced these splats to give projectiles something to leave behind when they explode. To 'influence' the visual aspect of the environment somehow. However, it appears the duration is really long on average. From 15 to 90 seconds, depending on the type of projectile.

With these changes we reduce the time by a lot. There were reports that splats were flickering. That means there's too much going on for the game to manage.

Related: https://discord.com/channels/197033481883222026/1431095378349916261

Testing done on the proposed changes

  • Seraphim tech 3 artillery
INFO: /projectiles/sifsuthanusartilleryshell01/sifsuthanusartilleryshell01_proj.bp	61.527900695801	 -> 	18.7639503479
INFO: /projectiles/sifsuthanusartilleryshell01/sifsuthanusartilleryshell01_proj.bp	69.272018432617	 -> 	22.63600730896
INFO: /projectiles/sifsuthanusartilleryshell01/sifsuthanusartilleryshell01_proj.bp	49.695949554443	 -> 	12.847974777222
INFO: /projectiles/sifsuthanusartilleryshell01/sifsuthanusartilleryshell01_proj.bp	61.96985244751	 -> 	18.984926223755
INFO: /projectiles/sifsuthanusartilleryshell01/sifsuthanusartilleryshell01_proj.bp	51.62414932251	 -> 	13.812074661255
INFO: /projectiles/sifsuthanusartilleryshell01/sifsuthanusartilleryshell01_proj.bp	51.403820037842	 -> 	13.701910972595
INFO: /projectiles/sifsuthanusartilleryshell01/sifsuthanusartilleryshell01_proj.bp	85.869422912598	 -> 	30.934711456299
  • UEF tech 1 artillery
INFO: /projectiles/tiffragmentationsensorshell02/tiffragmentationsensorshell02_proj.bp	23.328428268433	 -> 	7.6642141342163
INFO: /projectiles/tiffragmentationsensorshell02/tiffragmentationsensorshell02_proj.bp	19.083351135254	 -> 	5.5416750907898
INFO: /projectiles/tiffragmentationsensorshell02/tiffragmentationsensorshell02_proj.bp	17.808380126953	 -> 	4.9041900634766
INFO: /projectiles/tiffragmentationsensorshell02/tiffragmentationsensorshell02_proj.bp	18.811252593994	 -> 	5.4056258201599
INFO: /projectiles/tiffragmentationsensorshell02/tiffragmentationsensorshell02_proj.bp	16.3460521698	 -> 	4.1730265617371
INFO: /projectiles/tiffragmentationsensorshell02/tiffragmentationsensorshell02_proj.bp	20.587032318115	 -> 	6.2935161590576
INFO: /projectiles/tiffragmentationsensorshell02/tiffragmentationsensorshell02_proj.bp	19.030111312866	 -> 	5.5150556564331
INFO: /projectiles/tiffragmentationsensorshell02/tiffragmentationsensorshell02_proj.bp	18.897994995117	 -> 	5.4489970207214
INFO: /projectiles/tiffragmentationsensorshell02/tiffragmentationsensorshell02_proj.bp	21.593914031982	 -> 	6.7969574928284
INFO: /projectiles/tiffragmentationsensorshell02/tiffragmentationsensorshell02_proj.bp	22.86612701416	 -> 	7.4330635070801
INFO: /projectiles/tiffragmentationsensorshell02/tiffragmentationsensorshell02_proj.bp	16.53436088562	 -> 	4.2671804428101
INFO: /projectiles/tiffragmentationsensorshell02/tiffragmentationsensorshell02_proj.bp	20.366186141968	 -> 	6.1830930709839
INFO: /projectiles/tiffragmentationsensorshell02/tiffragmentationsensorshell02_proj.bp	19.865161895752	 -> 	5.932580947876
INFO: /projectiles/tiffragmentationsensorshell02/tiffragmentationsensorshell02_proj.bp	20.242944717407	 -> 	6.1214723587036
INFO: /projectiles/tiffragmentationsensorshell02/tiffragmentationsensorshell02_proj.bp	16.518728256226	 -> 	4.2593636512756
INFO: /projectiles/tiffragmentationsensorshell02/tiffragmentationsensorshell02_proj.bp	22.034484863281	 -> 	7.0172424316406
INFO: /projectiles/tiffragmentationsensorshell02/tiffragmentationsensorshell02_proj.bp	16.850700378418	 -> 	4.4253497123718
INFO: /projectiles/tiffragmentationsensorshell02/tiffragmentationsensorshell02_proj.bp	19.455581665039	 -> 	5.7277908325195
INFO: /projectiles/tiffragmentationsensorshell02/tiffragmentationsensorshell02_proj.bp	23.924781799316	 -> 	7.9623908996582
INFO: /projectiles/tiffragmentationsensorshell02/tiffragmentationsensorshell02_proj.bp	21.143238067627	 -> 	6.5716190338135
INFO: /projectiles/tiffragmentationsensorshell02/tiffragmentationsensorshell02_proj.bp	19.372924804688	 -> 	5.6864624023438
INFO: /projectiles/tiffragmentationsensorshell02/tiffragmentationsensorshell02_proj.bp	20.787008285522	 -> 	6.3935041427612
INFO: /projectiles/tiffragmentationsensorshell02/tiffragmentationsensorshell02_proj.bp	19.692874908447	 -> 	5.8464379310608
INFO: /projectiles/tiffragmentationsensorshell02/tiffragmentationsensorshell02_proj.bp	22.806102752686	 -> 	7.4030513763428
INFO: /projectiles/tiffragmentationsensorshell02/tiffragmentationsensorshell02_proj.bp	18.096109390259	 -> 	5.0480546951294
INFO: /projectiles/tiffragmentationsensorshell02/tiffragmentationsensorshell02_proj.bp	18.839860916138	 -> 	5.4199304580688
INFO: /projectiles/tiffragmentationsensorshell02/tiffragmentationsensorshell02_proj.bp	23.918785095215	 -> 	7.9593930244446
  • UEF Tech 2 point defense:
INFO: /projectiles/tdfgauss02/tdfgauss02_proj.bp	26.544828414917	 -> 	8.4724140167236
INFO: /projectiles/tdfgauss02/tdfgauss02_proj.bp	29.437366485596	 -> 	9.9186820983887
INFO: /projectiles/tdfgauss02/tdfgauss02_proj.bp	28.735557556152	 -> 	9.5677785873413
  • UEF Tech 3 strategic bomber:
INFO: /projectiles/tifsmallyieldnuclearbomb01/tifsmallyieldnuclearbomb01_proj.bp	85.541320800781	 -> 	29.770658493042
  • Fatboy
INFO: /projectiles/tdfgauss04/tdfgauss04_proj.bp	26.960863113403	 -> 	8.4804315567017
INFO: /projectiles/tdfgauss04/tdfgauss04_proj.bp	26.168601989746	 -> 	8.084300994873
INFO: /projectiles/tdfgauss04/tdfgauss04_proj.bp	31.613891601563	 -> 	10.806945800781
INFO: /projectiles/tdfgauss04/tdfgauss04_proj.bp	28.755882263184	 -> 	9.3779411315918
INFO: /projectiles/tdfgauss04/tdfgauss04_proj.bp	31.762907028198	 -> 	10.881453514099
INFO: /projectiles/tdfgauss04/tdfgauss04_proj.bp	23.314832687378	 -> 	6.6574158668518
INFO: /projectiles/tdfgauss04/tdfgauss04_proj.bp	21.514802932739	 -> 	5.7574014663696
INFO: /projectiles/tdfgauss04/tdfgauss04_proj.bp	21.019285202026	 -> 	5.509642124176
INFO: /projectiles/tdfgauss04/tdfgauss04_proj.bp	26.288417816162	 -> 	8.1442089080811
INFO: /projectiles/tdfgauss04/tdfgauss04_proj.bp	23.838871002197	 -> 	6.9194355010986
INFO: /projectiles/tdfgauss04/tdfgauss04_proj.bp	25.736152648926	 -> 	7.8680758476257
INFO: /projectiles/tdfgauss04/tdfgauss04_proj.bp	27.2214012146	 -> 	8.6107006072998
INFO: /projectiles/tdfgauss04/tdfgauss04_proj.bp	25.528570175171	 -> 	7.7642850875854
INFO: /projectiles/tdfgauss04/tdfgauss04_proj.bp	23.579916000366	 -> 	6.7899580001831
INFO: /projectiles/tdfgauss04/tdfgauss04_proj.bp	24.254306793213	 -> 	7.1271533966064
INFO: /projectiles/tdfgauss04/tdfgauss04_proj.bp	28.734312057495	 -> 	9.3671560287476
INFO: /projectiles/tdfgauss04/tdfgauss04_proj.bp	24.287525177002	 -> 	7.143762588501
INFO: /projectiles/tdfgauss04/tdfgauss04_proj.bp	27.446649551392	 -> 	8.7233247756958
INFO: /projectiles/tdfgauss04/tdfgauss04_proj.bp	25.849029541016	 -> 	7.9245147705078
INFO: /projectiles/tdfgauss04/tdfgauss04_proj.bp	24.275653839111	 -> 	7.1378264427185

Additional context

Related: #5616 and #3719

Checklist

Summary by CodeRabbit

  • Bug Fixes
    • Adjusted projectile splash effect duration to display more appropriately based on blast radius parameters.

@coderabbitai
Copy link

coderabbitai bot commented Oct 28, 2025

Walkthrough

A local variable duration is introduced in lua/sim/Projectile.lua with recalculated coefficients and replaces a hardcoded duration argument passed to CreateSplat. The duration formula changes from 8 + 8 * altRadius + 8 * rngRadius to 2 + 2 * altRadius + 4 * rngRadius.

Changes

Cohort / File(s) Summary
Projectile splat duration refactoring
lua/sim/Projectile.lua
Extracts duration calculation into a local variable with adjusted coefficients; replaces inline duration argument in CreateSplat call, reducing splat lifetime values.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

  • Verify the new duration coefficient values are intentional and do not introduce unintended behavior
  • Check if there are other locations where similar duration calculations need updating for consistency

Suggested reviewers

  • lL1l1
  • BlackYps

Poem

🐰 A splash of math, a tweak so neat,
Duration danced to a quicker beat,
Coefficients changed, the splat will fade,
In half the time, a cleaner trade!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The pull request title "Reduce duration of splats made by projectiles" directly and accurately summarizes the main change in the changeset. The raw summary confirms that the modification involves reducing the duration calculation for splats from 8 + 8 * altRadius + 8 * rngRadius to 2 + 2 * altRadius + 4 * rngRadius. The title is concise, specific, and clearly communicates the primary change without vague language or unnecessary details.
Description Check ✅ Passed The pull request description follows the repository template and includes all major required sections. The "Description of the proposed changes" section clearly explains the rationale (splats had excessive durations of 15-90 seconds, causing flickering and performance issues) and references relevant discussions. The "Testing done on the proposed changes" section provides comprehensive logging data for multiple projectile types showing the before-and-after duration reductions. The "Additional context" section includes relevant GitHub issue references, and the checklist is present, though two items remain unchecked (changelog snippet and reviewer assignment are pending tasks rather than missing description content).
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 440dd30 and 3bcd61f.

📒 Files selected for processing (1)
  • lua/sim/Projectile.lua (2 hunks)
🔇 Additional comments (1)
lua/sim/Projectile.lua (1)

437-448: LGTM! Splat duration reduction is well-implemented.

The introduction of the duration variable with reduced coefficients (from 8 + 8 * altRadius + 8 * rngRadius to 2 + 2 * altRadius + 4 * rngRadius) achieves the PR objective of reducing splat lifetimes. The formula maintains positive durations (minimum ~2 seconds) and scales appropriately with projectile damage radius. Testing data in the PR description demonstrates substantial reductions across multiple projectile types without obvious visual issues.


Comment @coderabbitai help to get the list of available commands and usage tips.

@BlackYps
Copy link
Contributor

How did you come up with the new formula?

It's important to note that shorter is not necessarily better. There is a tradeoff because ideally we would display all splats forever. The game engine has a limit, so we need a time duration. This time should be as long as possible without hitting the limit too much, when the time is longer then the battlefiled looks more interesting, because things don't turn back to normal so fast. The problem is that it is not obvious what time that would be. The amount of splats produced in games can be vastly different. Without further context I think it is premature to reduce the splat times by a lot.

@Garanas
Copy link
Member Author

Garanas commented Oct 28, 2025

The new formula is essentially a random adjustment - the numbers feel decent enough. For larger explosions it remains roughly half a minute. For very small ones (we're talking about tech 1 artillery) the LOD is so low that you won't even see them in general. It's fine if these disappear within seconds I think.

There is a tradeoff because ideally we would display all splats forever.

I don't agree with this - it would clutter the screen eventually. But that's beyond the point.

I personally think the limit for the number of splats of the engine is quite low. A hundred tech 1 tanks can already cross the same limit using treads. That's why they were reduced the life time of treads in #6089, which was again a reduction of #5132, which was a reduction of the original value in Steam:

CreateSplatOnBone(self, boneTable.Tread.TreadOffset, 0, boneTable.Tread.TreadMarks, boneTable.Tread.TreadMarksSizeX, boneTable.Tread.TreadMarksSizeZ, 100, boneTable.Tread.TreadLifeTime or 15, army )

Which defaults to 15 seconds for all units!

This value makes sense when the average game has a unit cap of 250 or 500 units, like on launch. But now when there can easily be 4000-6000 units of which half of them may create treads the limit is just insufficient. And then we at FAForever included these splats that are made by projectiles on top of it 😄!

When the limit is passed it can create various artifacts, ranging from splats not spawning, flickering of splats and even having other splats being rendered in splats (Fatboy is most notable here, where mass extractor splats end up mashed into the treads rendering somehow. I don't have a screenshot, unfortunately).

Anyway, I don't personally really mind one way or another. I think these values are fine and I suspect they help fix some of the artifacts, given that ~50 tech 1 artillery artillery with split projectiles can easily generate hundreds of splats per second.

@zhanghm18GIT
Copy link

The test was conducted using the FAF release version. Just have many Fatboys fire at multiple positions simultaneously and you can observe that the craters suddenly disappear and reappear when the camera is moving or zooming. Moreover, when multiple units are moving at the same time, many treads fail to generate properly. For instance, in the video, the large treads of the Fatboy only generated a short section.

4.mp4
3.mp4
2.mp4
1.mp4
5.mp4

@zhanghm18GIT
Copy link

zhanghm18GIT commented Oct 29, 2025

@Garanas One question is whether this method will completely "remove" the crater after a period of time, making it no longer exist on the map, or whether it will merely make the crater "invisible", still existing on the map but simply being "unobservable".

I just tried using this code, and I set the "duration" of all craters to "1". Although all craters disappeared after 1 second, the tracks soon stopped displaying normally. I don't think this helps with the issue of flickering decals after playing the game for a while.

Ah, I think compared to craters, track marks seem to have a greater impact on this issue. I tried moving a large number of UEF T3 artillery (about 200) together, and even if no units on the map were firing, the track marks generated by the movement of a large number of units would still cause the decal to flicker.

1.mp4

I think just 200 UEF T3 artillery pieces moving simultaneously would be enough to make the game's decals flicker, and even the textures of the power markers on the map would flicker abnormally.

I think the game engine simply cannot support 200 units generating track tracks simultaneously.

2.mp4

I changed the duration of all track tracks to 0, and the problem of the map's power indicator flashing when 200 T3 artillery pieces moved was solved.

I believe that track tracks also present a problem of excessive decal generation in a short period of time. Each unit generates multiple track tracks within 1 second, and even with the current track track disappearance time, hundreds of units can generate thousands of decals in just a few seconds. This results in a far greater number of instantaneous decals than projectiles.

In summary, craters generate continuous, cumulative decals, and their duration needs to be shortened to prevent excessive accumulation over time. Track tracks, on the other hand, generate excessive decals in a short burst, which may require alternative solutions. For example, completely eliminating track tracks and replacing them with a larger, more noticeable dust effect when all units move, or some other method, could prevent a single unit from generating a large number of decals in a short period of time during movement.

@Garanas
Copy link
Member Author

Garanas commented Oct 30, 2025

For example, completely eliminating track tracks and replacing them with a larger, more noticeable dust effect when all units move, or some other method, could prevent a single unit from generating a large number of decals in a short period of time during movement.

I don't agree with this. There is no good solution here. It boils back to what I wrote earlier:

This value makes sense when the average game has a unit cap of 250 or 500 units, like on launch. But now when there can easily be 4000-6000 units of which half of them may create treads the limit is just insufficient.

And to what BlackYps wrote:

It's important to note that shorter is not necessarily better. There is a tradeoff because ideally we would display all splats forever. The game engine has a limit, so we need a time duration.

The best we can do is to make the best with what we have. I don't think that removing a feature like tracks (or the splats for projectiles) is a good approach when it's not a problem on a lot of maps and army configurations. The tweaking of these values still make sense though, as it may allow us to support more maps and army configurations without artifacts.

Unrelated, but since you mention it: using emitters is also not a great solution. Emitters can cause stutters. The game rewinds all emitters if they were not visible before as you are zooming in. All emitters have an LOD value, just like splats, decals and meshes. This is why the generated trail emitters of all units are much shorter than in the Steam version. In the Steam version they'd last about half a minute or longer. In FAForever it is reduced to a few seconds.

We can maybe make the emitters easier to see, as all variations except snow can be hard to see at all in my opinion.

@zhanghm18GIT
Copy link

zhanghm18GIT commented Oct 30, 2025

For example, completely eliminating track tracks and replacing them with a larger, more noticeable dust effect when all units move, or some other method, could prevent a single unit from generating a large number of decals in a short period of time during movement.

I don't agree with this. There is no good solution here. It boils back to what I wrote earlier:

This value makes sense when the average game has a unit cap of 250 or 500 units, like on launch. But now when there can easily be 4000-6000 units of which half of them may create treads the limit is just insufficient.

And to what BlackYps wrote:

It's important to note that shorter is not necessarily better. There is a tradeoff because ideally we would display all splats forever. The game engine has a limit, so we need a time duration.

The best we can do is to make the best with what we have. I don't think that removing a feature like tracks (or the splats for projectiles) is a good approach when it's not a problem on a lot of maps and army configurations. The tweaking of these values still make sense though, as it may allow us to support more maps and army configurations without artifacts.

Unrelated, but since you mention it: using emitters is also not a great solution. Emitters can cause stutters. The game rewinds all emitters if they were not visible before as you are zooming in. All emitters have an LOD value, just like splats, decals and meshes. This is why the generated trail emitters of all units are much shorter than in the Steam version. In the Steam version they'd last about half a minute or longer. In FAForever it is reduced to a few seconds.

We can maybe make the emitters easier to see, as all variations except snow can be hard to see at all in my opinion.

I understand what you mean. The track mark is indeed a very good feature. But as you can see from the video, only 200 units with tracks are needed to make the decals in the game map flicker. I think it's very easy to achieve this number of units in most maps and battles.

Also, it's just a personal request. Could you release a MOD that can remove all the track marks from T1 to t3 units and only keep the track marks of the experiment-level units? I think this would be very helpful.

At the same time, I think it's worth a try to magnify the emitters generated when T1 - T3 units move. Since these emitters that have already been produced take up performance, it's best to make them more obvious.

@zhanghm18GIT
Copy link

@Garanas I've noticed that each land unit has a GroundKickup01. If I change GroundKickup01 to GroundKickup02, the unit's movement animations become much better (more noticeable smoke effects).In this situation, even without track tracks, there can be a good effect on land unit movement.

01.mp4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants