2,216 Commits over 549 Days - 0.17cph!
Tests: OcclusionGroupTests - add TestVisibilityAfterMovementAway tests (32)
Tests: ran new unit tests, 14 fail
Tests: OcclusionGroupTests - Visibility tests now update network groups and update subscriptions
This validates that subscription mechanism works on a basic level
Tests: all 42 unit tests pass
Bugfix: OcclusionGroupTests - use AreEquivalent instead of AreEqual when comparing occlusion groups
Old logic and new logic end up with differently ordered occlusion groups - but in real world we don't care about order
Tests: all 42 unit tests pass
Bugfix: Eagerly initialize occlusion groups when player spawns
When player's network group switches on spawn, it's treated as a bot, so doesn't create an occlusion group, but it might be awhile till next group switch, so player might have uninitialized occlusion group for a bit.
Tests: unit tests - 42/45 pass
Bugfix: OcclusionGroupTests - handle dead players in limbo
All TestVisibility* tests pass for old logic
Tests: ran unit tests
Bugfix: OcclusionGroupTests - use RespawnAt to be put in the right position for RespawnFromDead players
This makes 3 unit tests pass
Tests: ran unit tests
Bugfix: PlayerInventory - make GiveDefaultItems safe, report errors instead of NREing
- GameManager.InUnitTest is now available outside of UNITY_EDITOR as always-false const
Tests: more unit tests related to RespawnFromDead pass
Update: OcclusionGroupTests - introduce another player spawn state, RespawnFromDead
- setup default itemList for ItemManager when running unit tests, as it's assumed to always be there
Another assumption that I had proved wrong - when players are spawned, they can stay dead (for example, game mode can prohibit spawning for a time)
Tests: ran unit tests, more borkage
Bugfix: OcclusionGroupTests - setup valid world bounds for unit tests
- added netgroup visibility precondition testing, if that fails, then the test setup is wrong
Empty bounds were causing group layers to sometimes become TutorialIsland, which break visibility
Tests: ran unit tests, more pass
Bugfix: OcclusionGroupTests - correct expectations of visibility
Tests: ran unit tests, more pass, but still mostly borked
Tests: OcclusionGroupTests - add players that spawn as sleepers or dead
I assumed newly connected players always spawn as sleepers, but that's wrong - could explain an active NRE.
Tests: ran unit tests (most still borked)
Tests: add basic OcclusionGroup tests
- covers both old and new logic
Tests: ran unit tests, most fail, only trivial passes. Will resolve tomorrow.
Merge: from useplayertasks_removegroupocludee_nre
- Update: hide new server occlusion group logic behind -enable-new-server-occlusion-groups command line arg (disabled by default)
Tests: 2p on Craggy - moved, teleported, reconnected, checked server occlusion still works
Update: merge old OcclusionGroup code and put it behind DisableNewOcclusionGroups switch
- make DisableNewOcclusionGroups true by default, can be turned off with -enable-new-server-occlusion-groups command line arg
Tests: 2p on Craggy - moved, teleported, reconnected, checked server occlusion still works
Update: declare a boot time switch to disable new server occlusion groups
Need to bring back old logic for it, that'll be next.
Tests: none, trivial change
Merge: from useplayertasks_removegroupocludee_nre
- Bugfix: a series of bugfixes and extra error logs to ensure occlusion groups are valid and consistent
Tests: 2p on Craggy - ran around host, flew away and back, teleported away and back, tested sleepers, disconnects, and general occlusion
Clean: move OcclusionValidateGroups servervar to ServerOcclusion
- codegen
Tests: server compiles
Clean: GetOccludees => OcclusionGroup getter
Tests: server compiles
Clean: OcclusionGroups - define bespoke ServerOcclusion.Group
- updated code references
Tests: all modes compile in editor
Clean: OcclusionGroup - lower core of logic from BasePlayer to BaseNetworkable
- also move cached subscribers cleanup to BasePlayer.OnServerDestroy
- split off server occlusion logic into it's own BaseNetworkable potion
Tests: all platforms compile in editor
Bugfix: ServerOcclusion - clean up external references when BaseNetworkable is destoyed
Dobbie's free, this is the last bug I could theorycraft. There's a small window before occlusion would update and unsubscribe where a teleport then destroy could leave a dangling set of references, but this doesn't happen because of unnecessary SetParent being called when BaseEntity is destroyed on the server(but this should be fixed separately)
Tests: not testable
Update: OcclusionGroup - tracked down another false-positive error
- left a comment explaining why check was removed
Whena player reconnects and reclaims a sleeper with a player in proximity, the eventual network group subscription will try to append to the occlusion group that already contains the reconnected player.
Tests: reconnected with a player in vicinity
Bugfix: ServerOcclusion - clean up occlusion group refs when retiring groups
Fixes false-positive error logs
Tests: 2p, 2nd player disconnects while 1st player is in vicinity - afterwards first player walks out then back into to original network cell
Update: Update: OcclusionGroups - each members tracks which group refers to it
Needed for an upcomign bugfix in OnDestroy and helps detect issues
Tests: 2p on Craggy - tested players close, flying far away, teleporting, disconnect-reconnect - logged an extra problem to address
Clean: refactored out OcclusionOnDestroy, as it was getitng messy
- also added a null check to avoid pooling issues
Tests: none, trivial changes
Bugfix: OcclusionGroups - ensure sleepers are tracked when player transitions to a different occlusiongroup
This is an edge case when being in subscription range of a sleeper - sleeper's group would contain it and player, but player's group would have sleeper missing
Tests: moved around in the vicinity of sleeper, checked internal state
Bugfix: OcclusionGroups - fix NRE when moving out of group with a sleeper
- replaced with a IsVisibleFromFar check
- also reworked teleportation logic via IsVisibleFromFar, as that's more correct
- also IsVisibleFrom range check was wrong, so fixed that
Previous code relied on subscriber to check if move-out-of-bounds occurred, but sleepers don't have a subscriber, so it NREed
Tests: moved away from a cell with a sleeper, checked internal state
Update: NetworkVisibilityGrid gains IsVisibleFromNear/Far(Group from, Group to)
- expose via provider interface
Needed for occlusion groups case of moving sleepers (as I can't rely on subscriber check)
Tests: testted as part of followup bugfix
Bugfix: OcclusionGroups - eagerly clean up occlusion group when teleporting
- consolidated occlusion-group leaving logic
Caught the bastard - due to over-time nature of subscription updating, there was a window in which the player could teleport and disconnect, leading to a leak of occlusion group and a null participant.
Tests: on client, teleport2marker;kill, then separatelly disconnect; then on server run OcclusionValidateGroupson - all's gud
Update: minor changes
- comment explaining why occlusion group isn't retired
- error log for cases where we're unsubscribing from network group but we're not in it's occlusion group
- TODO comment outlining a desync between group transitions on the border of subscription range and networkable destruction
Tests: none, trivial changes
Bugfix: check if occlusion group participant is null when cleaning up occlusion groups
Should not be needed, but until I track down where nulls are happening this can prevent other issues
Tests: none, trivial change
Update: PersistentObjectWorkQueue now gathers a bit more telemetry
- also fixes a potential bug with stale data uploading to our backend (another case in ObjectQueue)
There's a bug with it being desynced with the rest of the data (it's called last, but in reality is current), will fix later
Tests: none, not done yet
Update: runtime_profiler - track pre_lateupdate times
It's a category with a bunch of unity internal work that can take a non-trivial amount of time. Should make it easier to identify source of degradation.
Tests: dryrun of analytics in editor with runtime_profiling 1
Merge: from useplayertasks_removegroupoccludee_nre
- Bugfix: patch exception from double add of occlusion group member. OcclusionValidateGroups to validate if groups are correct
Tests: various 2p scenarios - being close, far, outside of range, teleports
Update: add OcclusionValidateGroups servervar
- also replaced the conditional log with a logerror, to make sure we spot it
- codegen
Couldn't reproduce the issue locally, so I'm missing something, including whether it was a false-positive or not. This should help check every bad case and confirm whether the issue is legit or not
Tests: used the command in a couple scenarios - players close, players far, players outside of network range, with invis on/off
Update: replace throw with a devbuild-conditional error log
This is a cirtical code path, so we can't interrupt it or we'll corrupt global state. Think I see where the problem is coming from, will attempt to fix next
Tests: none, trivial change
Merge: from playerinventory_oncycle_optim
- Optim: iterate over cached items with OnCycle callback (instead of searching for them every time).
Tests: ran unit tests
Optim: ItemContainer.OnCycle now uses cached list of items with a callback
- added a perf test of 300 containers with ~10% items with OnCycle callback
Goes from 0.179 ms down to 0.074ms(-58%) for 300 player inventories. Real world server's invoke times are 0.97ms for 171 inventories, so might need to move it out of invokes later.
Tests: ran unit test
Tests: add ItemContainer.TestOnCycle test
Tests: ran unit tests
Merge: from useplayertasks_removegroupoccludee_nre
- Optim: rewrote how we manage occlusion groups to reduce their overall number and added pooling
- Bugfix: UsePlayerUpdateJobs 2 - no longer send extra snapshots when players move across network grid
Tests: 2p on Craggy - tested all occlusion interactions(fly away-back, hide behind terrain, use helicopter). Tested moving across grid with disconnecting 2nd player and killing them, validated occlusion groups. Monitored pooling via print_memory ListHashSet
Bugfix: when player disconnects, ensure we destroy relevant occlusion groups
- destroy local group if no local participants present
- remove destroyed participant from other occlusion group member's groups
Tests: 2p on Craggy in different cells - get 2nd player to disconnect, then kill sleepers. 1st player walks into the cell - no more NREs. Ran usual occlusion checks (fly away and back, hide behind terrain)
Optim: use pooling for occlusion groups
- prealloc 2k groups in the pool (1 per player and sleeper)
Tests: 2p on Craggy - nocliping across various grid cells and checking print_memory stats
Optim: ServerOcclsuion - rewrite how we track occlusion groups
- also fixes server occlusion bug which sends out more snapshots than necessary
Previously every network group in subscription range of player would create an occlusion group. Now, only occlusion-enabled entities populate their local cells (and their subscriber's local cells) - se get activeplayer+sleepers count max of occlusion groups.
Tests: both in UsePlayerUpdateJobs 0 and 2, 2 players on Craggy - ran around across network cells, flew outside of network range, used minicopter to fly into network range, checked sleeper is visible, checked kills clean up internal state. Player got occluded over terrain.
Merge: from triggerparentdelayedexit_optim
- Nothing, this just fixes merge history to avoid showing it as a non-merged branch
Tests: none, no files changed
Merge: from useplayertasks_invisplayers
- Bugfix for invisible player in helis/other vehicles with UsePlayerUpdateJobs 2
Tests: 2p on Craggy, flew heli to player outside of network range 5 times - player was visible