Performance Optimizations for Respawn

airoll

Member
Hello! I am currently profiling the performance of my game, and I notice that there are significant spikes whenever a character dies and respawns. Looking at the profiling information, it looks like it is taking 10 ms to respawn a character. Looking at the data in the image below, it looks like a lot of this is happening on the CharacterInventoryBridge.LoadDefaultLoadout() method. Is there any way to optimize this, or spread the workload over multiple fixed updates?

1638078905928.png
 
I tried profiling this in the integration demo scene but I don't see anything related to the Character Inventory Bridge.
In your case it seems that loadDefaultLoadout is the main problem.

How many items do you have in your default loadouts? do you really need to add the default loadout each time the character respawns or could you just make the character keep the items he had before death?

If you can't figure it out I'm afraid the best way for us to proceed is by sending us your project by sending us an email with a download link so that we can go through it in detail. But before you do add break points in the Character Inventory Bridge, LoadDefaultLoadout function and see if you can find anything that doesn't make sense.
 
Hi @Sangemdoko thanks for the response!

I only have four items in my default loadouts: (1) assault rifle, (2) assault rifle primary ammo, (3) assault rifle secondary ammo, (4) shield. The shield always stays on the character no matter what, so that's something that we could avoid re-creating each time the character respawns. The issue with the other three is that the character can pickup other weapons and unequip the assault rifle (and its ammo).

Now if I could effectively keep the assault rifle and its ammo in the character's inventory without allowing the character to equip the assault rifle, that might work. But I'm not sure what existing mechanism allows for that? Would I have to write custom code to disable item sets from being switchable to (when the player tries to unequip the assault rifle)? Any other less hacky approaches (like moving the item from an equippable item collection to a different item collection)?

Would love your thoughts here. I'm not sure why there's so much allocation time associated with creating an item. I only have these attributes for the Assault Rifle.

1638252892636.png
1638252911605.png
1638252932648.png
 
Here's an image of my Inventory component if it helps. When I look at the different purpose of the item collections, I see "Hide" and "Drop". Could I use those at all?

1638253152563.png
 
4 items shouldn't take that long to be dupplicated and added. You have a lot of Item attributes but that shouldn't be a reason for it to take that long.

The reason we dupplicate the Loadout items is because a Unique Item cannot be in two ItemCollections at the same time. And removing the item from the loadout would prevent you from loading the loadout multiple times.

(Don't worry about the purpose, you can leave them as is if you want, The only ones that are used in the system are Loadout and Hide to prevent them from appearing in the Inventory when doing a GetItemAmount(...). Equippable purpose is sometimes used in the ItemSlotCollectionView, but that's completely optional)

As you mentioned you could move the assault rifle to a hidden ItemCollection, but that's a bit hacky. Another option would be to create a custom loadout component that doesn't duplicate the item.

But I would really like to have a look at your project to understand why it is so slow to initialize the items and add them to the character. If you are able to it would be great if you could make a simple scene with just the character and a button that kills it to respawn. If you are able to replicate the issue there, then you can send us this scene with its dependencies so that we can have a deeper look at it. (Make sure you test the package in a new project before sending it to us at support@opsive.com)
 
Hi @Sangemdoko I've created a test project consisting of just the Opsive packages and demo scene, and added a script that kills the character every 0.5s (respawning in 0.1s), and sent that to support@opsive.com.

Test Project Profiling1638413070331.png

My Project Profiling
1638413167264.png

I also updated to the latest version of UCC / UIS and compared this test project to my project. Basically it seems like the difference boils down to the fact that I have a lot of attributes for my assault rifle, and that's causing a ~3ms difference in creating the item. That said, there's still a lot of overhead.

I am wondering about an alternative solution: What if I equipped my character with a default loadout of every weapon that the player can pick up in the game, but enable/disable item sets to simulate what the character actually has in their inventory (e.g. when a character picks up an item, it enables certain item sets)? This way, I wouldn't have to destroy all items on death, and create new items on respawn. Are there any downsides to this approach that you can think of?
 
Thank you for sending us your project, I'll ask Justin to forward it to me.

I am wondering about an alternative solution: What if I equipped my character with a default loadout of every weapon that the player can pick up in the game, but enable/disable item sets to simulate what the character actually has in their inventory (e.g. when a character picks up an item, it enables certain item sets)? This way, I wouldn't have to destroy all items on death, and create new items on respawn. Are there any downsides to this approach that you can think of?
That could be a potential solution. Unfortunatly the system wasn't really built with this way in mind. So you may need to write some custom code to support it.

You could have a default loadout for Equippable weapons. And then have another ItemCollection to add item to at runtime, which wouldn't be an Equippable ItemCollection to prevent items from being spawned multiple times.
Then you could make a custom ItemSetRuleObject which creates ItemSets depending on whether or not you have the item in this other ItemCollection.

Or instead of adding/removing the ItemSets with a custom ItemSetRuleObject you could just enable disable them using a custom script.

In the mean time I'll see if there is anything I can do to boost performance when respawning the character.

EDIT: Or perhaps, instead of removing all items, and loading the loadout. Why no create a script that only removes the items you want to remove on death? That might be a lot easier to do
 
Last edited:
Thanks for the suggestions. I am trying to better understand exactly what you described.
  1. Create a loadout with every weapon and have that give to an ItemCollection A. Does it matter what Purpose it has or if its an Equippable Item Collection?
  2. Then when a player picks up a weapon, move that to an ItemCollection B. Does it matter what Purpose it has or if its an Equippable Item Collection? Then implement a custom ItemSetRuleObject that creates item sets based on what's in ItemCollection B.
  3. If we do this, does that mean when we create the loadout when the scene starts, the item objects will be created and parented to the Items object of the character (and also to the dominant hand of the character rig)? If not, what conditions need to be make sure that all the item objects are created ahead of time (at scene start)?
Your suggestion about removing only items that we want to remove on death would make sense in general, but for our case, since characters can only hold 2 weapons, they can drop the initial loadout weapon. That means that we would need to create the loadout weapon some of the time (if they dropped the weapon while alive).
 
Thanks to the project you sent us I belive I was able to reduce the processing for Death and respawn considerably.

For death I made the following changes:
  • added an option to prevent items from being dropped on death, so that they can simply be removed
  • In the integration I stop the bridgeEquippableProcessing from updating while I am Removing all items. And update only once the remove is complete.
  • Added a function to remove all items in the UIS inventory which disables executing the update event while looping over the items removed
  • Added the same disable executing update event functionality on UIS ItemCollections, when removing all items
  • Fixed a bug the Recipe Panel which was refreshing on inventory updated even thoug it was disabled
So now both Inventory and ItemCollection only send a single Update event after all items have been removed, instead of once for each item removed.
With those changes I went from 30ms on death to not being able to find it anymore in the profiler which means it should be under 2-4ms

For respawning/loading the default loadout I changed:
  • Creating Mutable Items is now more performant due to some changes on creating and dupplicating attributes at runtime.
  • In UCC improved Animator snapping to avoid as many OnAnimatorMove callbacks as possible
  • In the integration loading loadout now disabled itemCollection updates and BridgeEquippable events until all items are added, then the update is called manually.
With those changes we went from 40ms to under 20ms on respawn.

Things we still need to improve but cannot be done without major refactor:
  • Reduce string comparators with attributes
  • Creating Character item at runtime, even if they are pooled, there is still a lo of initialization time.
  • Creating Item Sets at runtime with the ItemSetRules. Creating ItemSets creates a Default State Preset at runtime which is slow.
  • SnapAnimator still calls Animator.Update() 2-3 times. It does so before and after items are added by the loadout.

Those are the main changes I made, I also made quite a few smaller changes. You should see some pretty big improvements once you use those changes.
But unfortunatly I made changes to alot of files so I can't send you everything in the forum. I also need to discuss with Justin to make sure the changes I made to UCC doesn't break anything. We also need to discuss the other points which could be refactored for performance.

Once we are happy with the changes and made sure they do not break anything we will release an update.
 
Top