When should TObjectPtr<T> be used outside of UPROPERTYs?

Is the recommended pattern to use TObjectPtr<T> only for UPROPERTY members within UCLASS and USTRUCT, and to use raw T* for function parameters and local variables? In other words, should TObjectPtr values generally be converted to raw pointers as soon as possible during usage?

Are there any edge cases where using TObjectPtr outside of properties (e.g., as function parameters or local variables) is expected or preferred?

The docu on https://dev.epicgames.com/documentation/en-us/unreal-engine/unreal-engine-5-migration-guide states:

Although it is optional, we recommend using TObjectPtr<T> over T* for UObject pointer properties and container classes found in UCLASS and USTRUCT types.

The code example shows both TObjectPtr and raw pointers used for function parameters with the TObjectPtr described as a rare exception to be used only if necessary.

Thanks for the answers, that confirms our approach as the correct one.

For example there are cases in the engine code where TObjectPtr is used locally, within a function, to store the result of creating an object with NewObject

Why is that done in those cases? Does it provide any benefits, such as for debugging?

Hi,

The short version:

The current rule of thumb is that you don’t need to use TObjectPtr outside of UPROPERTY members.

The longer version:

We have four current use cases for TObjectPtr:

  1. Access tracking during cook for computing dependencies for incremental cooks [experimental]
  2. Allowing for incremental garbage collection [experimental]
  3. Facilitating remote object references on other machines [pre-experimental]
  4. Allowing for lazy load of imported references [not currently used]

Each of these usage scenarios has slightly different needs, and these usage scenarios change over time. But we need consistent guidance for TObjectPtr usage that doesn’t change with the usage scenarios, and the simple rule of thumb above is adequate. There are a few situations where you might have a frequently running inner loop with some condition that receives TObjectPtr and converts them to raw pointers, and that will function correctly but cause every TObjectPtr to count as being accessed and trigger the access tracking logic even if the condition doesn’t pass and we don’t actually access it. That’s an example of a situation where it can be desirable to not convert from TObjectPtr to raw pointer. But these are abnormal and not something that should be part of general guidance.

A more complete rule would be: Use TObjectPtrs when you have object references that will be expected to span a garbage collect.