The drive ability can be synced over the network like any other abilities so that part is no problem. The problem appears with the actual vehicle controller. The SkyCar controller was taken from one of Unity's sample assets so it doesn't have network support. You'll need to add in the support yourself.
Thanks for the quick response. I implemented network support for my car controller. I think this is not the main issue. It is more the IDriveSource component I am not sure how to sync. It is somehow part of the ability, but is not synced yet. Has it to be synced through any of the Opsive PUN components?
Which part are you finding needs to be synced? When the ability on the remote client starts it will call EnterVehicle, and ExitVehicle when the ability stops. The Entered/ExitedVehicle callbacks should be called with the animation event which gets sent from the animation.
With all of that said, I haven't actually tried this because I don't have a networked vehicle controller so I could be wrong.
Is there anything specific I have to do so that the ability is called on the remote client? Because it is not called in my setup. For instance, the rigidbody is still set to kinematic. I would have expected that it is similar to the interaction ability where the interaction is explicitly called via RPC on the remote clients.
I got a little further in my analysis. So, I verified that the ability change to drive is reliably sent and received via RPC every time I start the ability. But then most of the times the drive ability is not executed on the remote client. Sometimes it is executed (no idea under which condition), the vehicle is entered, the car is enabled, but then immediately the car is disabled again, and the OnExitedVehicle method is called. Though the player remains in the car as it is synced through the controller.
For some reasons the base.CanStartAbility() call in the drive script returns false. Only sometimes it returns true. But actually, on the remote client the ability shouldn't be checked at all, or?
When the ability starts on the master client it will be synced across to the other clients with PUNCharacter.StartAbilityRPC. StartAbilityRPC will ignore the CanStart check so you're right in that it shouldn't return false.
Even though it's not networkable I will add the SkyCar to the PUN demo scene and see if I can at least get the correct callbacks. If they aren't working I'll have it fixed in the next update.
Thanks, that would be great. I think this test should work without at networking controller. There would be two additional requirements for a networking drive ability. First, the driver should receive ownership over the car to be able to distinguish the driver from other players. And second, when a player is driving, the ability should be disabled for all other players to prevent them from entering an already occupied car.
I looked into this and it looks like EnteredVehicle/ExitedVehicle is called from the animation events but EnterVehicle/ExitVehicle is not called. I was thinking about adding callbacks to the drive ability, but I actually think that it would be better if you added it to your own IDriveSource implementation. This will give you complete control over the implementation for your two requirements. It also makes sense because it is the vehicle that is performing the operations rather than the character itself.
I will add checks to the Drive ability to abort early if the character is not the local player so you won't get the callback multiple times.
I can handle the ownership on my own. For checking whether the car is occupied it is getting a little tricky. Right now the IDriveSource does not include a method / property for checking the car's state. So I can't use the IDriveSource directly n the CanStartAbility() method (only if I add another component just to hold the state, similar to the MoveTowardsLocation). I was wondering whether there are other use cases for having a state in the interface. For instance, if a car is damaged and can't be used before repair.
That's a good point. Just because there are a lot of different possible states that could/could not prevent you from being able to drive the vehicle, I recommend subclassing the Drive ability and then get a reference to your component that implements IDriveSource. This will then allow you to add any state that is necessary.
(on a side note your vehicle implementation sounds like it is going to be really neat.. make sure you post a video of it working when you're done with it!)
For my case I have decided to implement my own car interface and ability. That's the only way to get a consistent state with two players and a driver and passenger option. Everything works fine except for one thing that also affects the standard drive ability and IDriveSource interface.
I start with two players, both do not interact with the car before both players have entered the room. After that any of the players can interact with the car without any issues. Both can be driver or passenger. Ownership and control is changed accordingly. Everything is fine.
Now, if the first player enters the room and enters the car before the second player enters the room, the state is not synchronized at all. The issue is that the state synchronization depends on processing the ability including the animations from start to end. But when the first player is already in the car, the ability is not executed on the second client, as the position of the player in the car is automatically synchronized. As a result, the first player on the second client has no IDriveSource assigned, the colliders are not ignored / disabled, the animation state is not correct, and the character is not a child of the car.
For my prototype I can live with it, as I can avoid the situation. But for production this is a real issue, and I don't see any easy fix for that.