Facepunch / sbox-issues

175 stars 12 forks source link

Transforms Sometimes Randomly Break #5290

Closed anthonysharpy closed 7 months ago

anthonysharpy commented 7 months ago

Describe the bug

I've been getting this weird issue in my project for a while where the transforms suddenly seem to break. I might be doing something weird but the issue seems to be internal, judging from the stack trace?

2024/03/27 22:15:31.3448    [GameMenu] Exception when calling 'FixedUpdate' on Player on (player)   System.NullReferenceException: Object reference not set to an instance of an object.
   at Sandbox.GameTransform.set_Local(Transform value)
   at Sandbox.GameTransform.set_LocalPosition(Vector3 value)
   at SandboxCity.SkeletonCarBase.RaycastWheels() in C:\Users\antho\Documents\s&box projects\sandbox_city\code\entities\vehicles\SkeletonCarBase.cs:line 521
   at SandboxCity.SkeletonCarBase.DoUpdate() in C:\Users\antho\Documents\s&box projects\sandbox_city\code\entities\vehicles\SkeletonCarBase.cs:line 440
   at SandboxCity.DriveableCar.DoUpdate() in C:\Users\antho\Documents\s&box projects\sandbox_city\code\entities\vehicles\driveable\DriveableCar.cs:line 128
   at SandboxCity.SkeletonCarBase.FixedUpdate() in C:\Users\antho\Documents\s&box projects\sandbox_city\code\entities\vehicles\SkeletonCarBase.cs:line 402
   at SandboxCity.Player.OnFixedUpdate() in C:\Users\antho\Documents\s&box projects\sandbox_city\code\player\RolePlayer.cs:line 1569
   at Sandbox.Component.ExceptionWrap(String name, Action a)

The line of code that triggers it is this:

FrontLeftWheel.Transform.LocalPosition =
    FrontLeftWheel.Transform.LocalPosition.WithZ( Math.Clamp( WheelDiameter - FrontLeftDistance, 0, float.MaxValue) );

If I log the value being used in WithZ it seems reasonable, it's just a regular float

To Reproduce

I have a way of reproducing this... it's sort of specific to my game but it's:

I can (usually) avoid the issue by doing this:

My guess is that when you stop the game, the transforms somehow are not getting reset properly, or are getting corrupted?

Sometimes this issue randomly happens even if I leave the vehicle before stopping the game though

BTW, once this error starts happening on a particular car, I have to reset s&box to get it to work again. But one workaround for me is to just duplicate the car, and then that car starts working (so the issue definitely seems to be tied to the gameobject becoming corrupted somehow)

Expected behavior

No errors

Media/Files

No response

Additional context

Might be able to fix this just looking at the stack trace, but if not then let me know and I can email over a smallish repro project or something

kurozael commented 7 months ago

Hey @anthonysharpy can ya send a repro project to the email in my profile?

anthonysharpy commented 7 months ago

@kurozael Yeah sure no worries, will try and send one over asap

anthonysharpy commented 7 months ago

@kurozael Hey, sorry for the wait, have just sent this over today

kurozael commented 7 months ago

Weirdly, @anthonysharpy, herein lies the root of your issue: it's your caches in EntityHelper. If you disable / remove all your caching for ComponentCache and GOCache, you should find everything works as normal.

I believe the problem is that the GOCache and ComponentCache static Dictionaries are not being reset each time you start the game / load the scene. Meaning old references to components and GameObjects are being used - and for those references the GameObject.Scene is null. This causes your errors.

We should figure out internally how we wanna handle this kind of thing.

By the way, you can use Game.ActiveScene.Directory.FindById to find a GameObject by id, and it's fast because it's already a table lookup.

This is something we'll look at in the future, and I'll make a separate issue for the problem. For now, can you make sure you're handling the reset of these static properties yourself when the game is loaded?

Please see https://github.com/Facepunch/sbox-issues/issues/4164 for updates on this.

anthonysharpy commented 6 months ago

@kurozael Sorry just got back from holiday! Thank you for looking.

I believe the problem is that the GOCache and ComponentCache static Dictionaries are not being reset each time you start the game / load the scene. Meaning old references to components and GameObjects are being used - and for those references the GameObject.Scene is null. This causes your errors.

Ahh I'm so stupid. That makes sense. Sorry for wasting your time with it then, I just saw that the error was being thrown in the engine code and was hoping it wasn't me 🤣

By the way, you can use Game.ActiveScene.Directory.FindById to find a GameObject by id, and it's fast because it's already a table lookup.

Yeah there's a bunch of stuff like that I need to implement into my code, unfortunately I have more things to do than I have time these days 😞