When a player raise the sail on their raft and the raft is unloaded (with the sail up) (possibly from the player getting too far away from the raft like flying to another island or the raft sailing away, etc) it will throw a NullPointerException. Now I haven’t tested this so I cannot confirm it but I’ve seen how errors and exceptions can sometimes cause desyncs or even disconnects in online multiplayer. The solution to this problem is actually fairly straightforward and requires no more than 2 lines of code.
In short the issue occurs because of a minor mistake in the code. In the VehicleMovementBase class, two coroutines are created in the OnOperate() method, Input_Sequence and Movement_Sequence. But these coroutines are never killed in the event that the gameobject (with the VehicleMovementBase class component on it) would ever be unloaded (calling the component method OnDestroyed). The class SailMovementBase, which inherits the VehicleMovementBase class, uses the Unity Transform component in its IsOverturned() method which of course checks for if the raft is overturned. This is generally fine but because the Movement_Sequence() coroutine responsible for calling this method is never killed, when the raft is unloaded it will continue to try and use the raft’s transform which is of course point null at this point after being unloaed. This will in turn throw a NullPointerException.
The issue can be fixed by simply killing the two coroutines in the OnDestroy method in the VehicleMovementBase class (since all inheriting classes will be using these coroutines). So as promised, the issue fixed with two lines of code. Inside of the VehicleMovementBase class in the OnDestroy() method:
Another potential solution might be to call StopOperating() in VehicleMovementBase OnDestroy() but there are more if statements and checks in place so I can’t reassure that it will call the Operate() method that should otherwise kill the coroutines. But I’ll leave that up to the developers to decide. Personally I think the Timing.KillCoroutines in OnDestroy() is a simple solution but I can understand if another would be preferred. Possibly for calling events and such.
As far as I can tell this issue is present in the code of all the PC platforms. I checked the latest releases of Steam and Epic games (1.0.38, also present in older) and the 1.0.17 release of Xbox Gamepass (likely also presnet in older and newer versions as well).
What steps, if known, can cause this issue to occur for you?
- Build a raft
- Build a sail on the raft
- Build an anchor to keep the raft still (Optional)
- Operate/raise the sail
- Unload the raft (For example by flying to another island)
The image is showing the coroutines being created but never killed in OnDestroy() in the event the gameobject they’re attached to should be unloaed.