Download

Casting vs Class Equal To

“Casting” actually has a minor impact that may add up if you do it too much (inside Tick events of many actors, etc).
They could impact your code performance if abused, it’s worth watching this series if you didn’t already:

https://www.unrealengine.com/en-US/e…depth—part-1
https://www.unrealengine.com/en-US/e…depth—part-2

I have a widget debugger that is so riddled with tick casts that it more than halves the performance. It was getting so criminal that I now have tick boxes allowing sections of the debugger to do its thing. It does add up incredibility quickly when abused.

Cast returns an object or tells you it’s the wrong object type when it fails. *Equal *just tells you T/F. Apples vs oranges scenario, but the oranges are black and white and binary. You can’t compare the two.

If I understand the engine code correctly, casting creates a reference and makes sure everything is loaded or loads it if it’s not. So that’s why it can spiral out of control if you nest them or call them repeatedly.

Pretty much what I was told (and experienced), yeah. This also becomes painfully obvious with widgets, where nodes hang on to the references and Garbage Collection does not pick them up. Can be forced, of course. It’s a tad better these days but still manifests every now and then.

Yes but from a point of view of working out which object you are interacting with, personally I would have thought Class Equal would be quicker.

Technically you don’t even need to cast after that as you know that’s the class you are talking to.

I understand what you are saying about comparing the two, I personally just dont see the point in casting when class equal exists unless I am missing something obvious…

If the goal is to only determine whether it’s a specific object type or not, then I’d agree with this. Can’t back it up with hard data but I’d say Equal check should be virtually cost-free compared to a cast.

Of course you have to, in case you want to call a function or access a variable of the class you are casting to (except if you are using an interface). If you don’t need any specific data or call, then naturally there is no need to cast.

Actually the assets are pre-loaded, meaning that when the Blueprint asset is loaded, it checks which other assets it references to (and casts also add references), so it’s gonna increase the initial load time, casting itself does not load any new assets.

I’d be interested how can you force impure nodes to release the references for their cached output value (in case that’s what you are referring to).

That’s probably true for C++, maybe not so much in BP, as VM calls are kinda expensive, and while an impure Cast is 1 node, an equal check is at least 3.

You can manually call Collect Garbage (it is slow); it seems to work for return values providing there’s nothing else referencing the object. I’ve been having problems with widgets persisting despite clearing their references and removing them from their respective parents. This helped although I’m unsure what’s the scope of this method’s usefulness.

Not going to pretend I understand well enough how BP nodes parse (not even talking about nativization here). I do know they’re giant blocks of text and 3 is more than 1. So I’ll roll with that. Thanks for shedding some light on this.

Well, it would be great if it would be documented somewhere how long references in pins are hold. If for example you had a delay after an impure call, after which Delay you want to use the result of that node… can you be sure it’s not cleaned up yet? Or what are the exact rules for it? Sounds quite critical.

In some cases *indefinitely *prior to 4.17: “Assets that are only referenced by pins inside active Blueprints will now correctly be garbage collected. This means that if you use LoadAsset to load something and do not store it for future usage, it will no longer stay in memory forever until the loading Blueprint is destroyed.”

The GC was improved over the years and sped up but it was still an issue for widgets in 4.21. As of now, not sure, I’ve been manually keeping track of widgets and trashing them when numbers do not add up.

It will not be cleaned up. From my experience the result will be valid for as long as the calling object is valid *and *the return value actually points at something valid.

The problem arises when the opposite situation takes place, you attempt to destroy an object but the GC goes “ah, no, no - something is still referencing it” (the return value) so it’s going to be *pending kill *forever. I believe that *most *of those kinks have been ironed out, though.

Technically that’s not true in a blueprint, you can just get the actor ref you are talking about and take a pin straight to/from the function / variable.

You don’t have to cast at all in that case.

I really hope it will sort itself out and we don’t have to deal with it :smiley:

I don’t know what you mean, you can’t connect a non-Actor object to the pin of an Actor object (and it applies to every other class too, you can’t just connect a Widget to a function of a UserWidget without casting).

I think we are talking cross purposes here but you can most certainly take an actor object ref and directly access variables and functions without casting to it.

If you have the correct object type already (since we’re accessing its functions and vars) why the heck would you need to cast or check what class it is in the first place? That’s what we’re thinking. But…

This. Just to clarify, you do not care about accessing the object at all, right? You just want to test whether it is specific class or not. What is faster? A Success / Fail on cast vs Equal To.

These are faster :stuck_out_tongue:

As I said cross purposes … I guess I meant for an object of an already know type (sorry should have clarified that bit). I should have stated that you don’t have to cast in general to an already known object type.

So getting back on topic, yeah lets just say that you just want to know a type of object, you might not want to do anything with it necessarily, just simply to know what type of object you are talking about. In a pure simple form it seems to me like Equal To is the faster option in that case. Obviously if you want to do something with that object afterwards you would still be casting to it, so in that case just casting would be more efficient.

It does seem from some of the responses though that Casting has it overheads, hence the question.

If the cast is most usually successful here, won’t it be even slower? I’m pretty sure the Cast node itself also checks for failures (so that the failure check is done 2 times), and you also have an extra VM call (which is also expensive), and then we didn’t even talk about the extra complexity it adds to the graph.

It might still be useful in situations, but as far as I can see, it’s a bit of an overkill.

Independently, generally speaking, if there are so many casts that it actually affects performance, then something is likely wrong and the system could be restructured to avoid it.

Yeah, just stick to an Equal Check. It has another positive side: you can also compare it with a soft class, which won’t hold a hard reference, so that you might have a smaller footprint for your class (both Cast and a Hard Class Reference equality check will involve a hard reference).

No, that node doesn’t cast anything.
It checks class inheritance under a limited scope of classes. Casting has no scope and it always casts an object returning either a valid or null pointer.

That node always return uncasted object, no pointer math.

Sorry to bump up such an old but interesting discussion. I am at the same point and unsure if I should use “cast” or “get class and check equal”.
I do not need the cast, but cast is only one node. As someone said already, “get class and check equal” needs three nodes. But what is better? What is fast?

I think “cast” do a hard reference and when you compile the actor with the hard reference the actor which references to are compiled also. Is that true or a misunderstanding? Do this also happen on “get class and check equal” instead using cast?
No technical UE4 Evangelist here running around to solve such a interesting question? :slight_smile: , “get class and check equal” vs “cast to class”