spatialos / gdk-for-unity-fps-starter-project

SpatialOS GDK for Unity FPS Starter Project
https://gdk.improbable.io/spatialos-gdk-unity
MIT License
198 stars 75 forks source link

Thoughts on new-movement #76

Closed filod closed 5 years ago

filod commented 5 years ago

I've read the new-movement code roughly, nice work @mattyoung-improbable! and here's my naive feedback on it

  1. the issue i already posted on discord. character do a jump when i try to move right(i only press D key), i guess something gose wrong with AdjustVelocity or ApplyMovementProcessor, CharacterController use a collide and slide algorithm, so AdjustVelocity may do some wrong math in calc velocity (like go up stairs/slope)

image

  1. A more generic taken on CommandFrameSystem + client-prediction would be better. i'll give some reasons why:
    • CharacterController is actually part of phyiscs, such as doing RigidBody/projectile physics along with CharacterController movement, unity now can have multiple physics scenes & manully simulation step, it would be easy to fulfill gameplay based on physics if we extend the movement system. also the bug above is essentially making wrong assumption about how CharacterController behave.
    • Unity is planning a new C# based CharacterController, they said it's "equivalent of the PhysX CharacterController", so it will act more like kinematic object but with manually dynamic behaviors. I guess it should be easy to implement features like standing on moving object, Details still TBD
    • both Overwatch / Rocket League bring a network model doing client-prediction to all things (overwatch team even develop a node-based language named Statescript to make hero design easier)
  2. More docs would be better. i still can't figure out what PidController is doing.
mattyoung-improbable commented 5 years ago

Thanks so much for the feedback!

  1. I'm still not sure where this bug comes from, it seems to happen whenever you walk into a small step / land on an edge when jumping. Will do some investigations and try to isolate the issue. Might be character controller config with step height / capsule radius or something.
    • The CharacterController being passed in is leftover from before the pipeline when lots of the module used it. I think now the only part of the pipeline that uses it is the ApplyMovement processor, which could easily get the reference from somewhere else, making the pipeline completely generic.
    • Interesting, I'll check it out.
    • This is something I've been thinking about too. The next piece I'm working on is to encode all the input / movement data into a bytes field in schema and provide some API for getting / setting specific data. So if, for example you wanted analog movement instead of WASD, you could add a 2d vector into the input instead of 4 booleans. At that point, you could run any part of the game you needed to through the system.
  2. There will definitely be docs! And maybe even a tech talk if I'm feeling bold πŸ˜„
filod commented 5 years ago

haha, all sounds great. i'd like to watch your talk!

mattyoung-improbable commented 5 years ago

Some updates have happened!

  1. All the input / movement state is now defined outside the module in custom_movement.schema
  2. All the fps movement is handled by the FpsMovement class
  3. All references to CharacterController have been removed from the module, so you can bring your own controller πŸ˜„
  4. Under the hood, the custom types you define are being serialized / deserialized by the module, hopefully in the future there will be some Gdk features which will remove the need to do this.
  5. All the old IMovementProcessor have been quickly refactored for the new separation, they don't feel that great yet, need to figure out what level of abstract is best for users, will only come from experimenting though.
  6. Going to start on docs tomorrow I promise.
filod commented 5 years ago

haha, sounds great !

I checked out the new source, but i got this error when click play, and can not spawn player:

EntryPointNotFoundException: Schema_SerializeBuffer
Improbable.Worker.CInterop.SchemaObject.Serialize () (at <86c1bcc0c96e47b9ba174df556efe490>:0)
FpsMovement.SerializeStateStatic (Improbable.Fps.Custommovement.CustomState state) (at Assets/Fps/Scripts/GameLogic/FpsMovement.cs:168)
Fps.FpsEntityTemplates.Player (System.String workerId, Improbable.Vector3f position) (at Assets/Fps/Scripts/Config/FpsEntityTemplates.cs:49)

seems there is sdk/plugin version issue?

mattyoung-improbable commented 5 years ago

Oh oops, there's currently a bug in the Core Sdk. In your gdk directory you'll need to modify

gdk-for-unity/workers/unity/Packages/com.improbable.gdk.tools/core-sdk.version

to

13.5.0-b7977-97561-WORKER-SNAPSHOT

and then 'Download CoreSdk (force)' from the SpatialOS menu.

filod commented 5 years ago

i tried, but i got more errors (can't even compile correctly):

image

mattyoung-improbable commented 5 years ago

Ahh, might be some changes in core that are only in master. Could you checkout master of gdk and see if that works?

filod commented 5 years ago

it works for now, thx

just FYI, unity has released a very early version character controller: https://github.com/Unity-Technologies/Standard-Assets-Characters

i'll try to integrate it into this movement

mattyoung-improbable commented 5 years ago

Awesome! The code that touches the standard Character Controller is the CharacterControllerMovement.Move() static method. There shouldn't be any other references.

filod commented 5 years ago

Yes, unity SAC's OpenCharacterController is quite simple like the old CharacterController, but the concrete ThirdPersonBrain/FirstPersonBrain introduces many other complex concepts i'm still figuring that out.

filod commented 5 years ago

@mattyoung-improbable i'm trying to integrate SAC into new-movement recently, since SAC use RootMotion to calc final state, and we can't access unity's internal animation udpate, i'think we may need a async AbstractMovementProcessor.Process. but will this break CommandFrameSystem's assumption?

seems a huge headache... maybe RootMotion is not a good idea in networked game

mattyoung-improbable commented 5 years ago

Ah, that is annoying. The Movement Processor really needs to be deterministic for the system to work. One option might be to separate what the client sees locally from what gets passed through the movement system, and then manage syncing them up on the client. It's not ideal.

Might be worth taking a look at the character controller used in the unity Fps Sample Project, since that uses a similar approach to networking.

Another option would be something like https://github.com/AwesomeX/Fragsurf-Character-Controller/ which is a port of the Source engine character controller.

filod commented 5 years ago

FpsSample is not using RootMotion/SAC actually (afaik).

i'll eliminate RootMotion anyway. (i think it's a better way and without animation update also less server-cost)

filod commented 5 years ago

sorry to bother again, as i know new-movment is still a Character against static world simulation solution, it's hard to fulfill something like "walking on a moving boat", i'm wondering how to use CommandFrameSystem to achive RocketLeague-like physics among all workers. or there is a easy way using new-movement to achive the same result?

i noticed Overwatch guys said they still use a new-movemet-like solution, physics in Overwatch is not deterministic (if you try to hit a jar in spawn room, you will find its movment is not the same among different players' view), but they indeed have moving-platform in games (e.g. Volskaya Industries), so how they achive that anyway? (or the platform is actually just a TransformSync thing and it's not deterministic?)

hope i can get some hints.

mattyoung-improbable commented 5 years ago

For rocket league style physics. The client workers would need to keep track of all physics entities and use Physics.Simulate to manually step physics in the movement processor. You would need to add code to revert back and replay ALL physics entities locally during a replay. Rocket league can do this because they only have 7 physics entities (6 player cars + the ball). In spatial, you might need to rollback all physics actors within a certain distance from the player.

I've had a few ideas of how to do moving platforms / vehicles. One approach would be to use some kind of hierarchy. Whenever the player lands on a platform / vehicle, set a variable in the MovementState to indicate that the player's position is now relative to the platform / vehicle. Locally, you could actually set the parent game object of the player to the platform / vehicle and start updating local position. Anyone viewing the player remotely can do the same anchoring which would avoid visual problems where the player appears to float above the platform / clip through it due to interpolation delay. When the player jumps off the platform (and is far enough away from it) you would deactivate the parenting and revert back to global position.

Does that all make sense?

filod commented 5 years ago

thx for reply. ah.. parenting is actually a good way in networking situation, pubg definitely use that. but we have to trust client that he actually jump on that platform (on server side we can't see that happen), also after parenting, remote player could see my player "standing" behind a platform... any way, it's not a big deal when platform is slow and big (like a space ship), but i can't make a platformer game based on this...

i guess OW's moving platform maybe a special case in game with some lag-compensation stuff in it...

i got to say...networking is so hard... TAT

filod commented 5 years ago

@mattyoung-improbable

After digging around i realize full physics simulation may be the only choice to provide best experience.

  1. Moving-Platform is way more hard than i think, KCC's author gave some explain ref1 ref2, i checked kcc's code, to provide stable PhysicMover, you must simulate Character movement along with PhysicMover

  2. So, which rigidbody to correct? According Glenn Fiedler said , "At 90HZ simulation rate and with up to 250ms of latency to hide, this meant 25 physics simulation steps for each visual render frame. 25X cost is simply not realistic for a CPU intensive physics simulation" but i'll argue:

    1. physics frame rate can be lower than update frame rate (like new-movment did)
    2. In Glenn's Code, it use Rigidbody.IsSleeping to check if rigidbody is active, and we can increase sleepThreshold (bounding boxes is also feasible)
    3. In game design, we can reduce Rigidbody (and chain reactions) count
    4. ECS & job system is going to save, maybe (some examples shows real potential)

Responsiveness make a huge difference in game design, it could be a fundamental driven force. i'll do some experiments then.

mattyoung-improbable commented 5 years ago

Hey

  1. I think there's a middle ground between full parenting (not simulating the child) and a relative hierarchy (where the clients position information is stored relative to the moving platform, but they are still simulated). The advantage of doing this is that their position will make sense to remote players (they won't be floating behind the platform for example)

  2. If you're doing a full physics simulation and client worker receives a correction you would ideally rewind all rigidbodies in the scene back to that point before replaying them all again. One optimization would be to work out a bounding box around the body that needs correcting and only rewind anything inside that box, but you would need to take care how you calculate it.

One thing to decide is what's more important to your game: a) Every player seeing the exact same state of the world b) Every player seeing a state of the world that appears consistent (doesn't break the laws of physics etc)

Also @zeroZshadow is taking over the movement features for a while!

jamiebrynes7 commented 5 years ago

Thank you for the feedback!

As the new movement feature module has been dropped from the roadmap, this issue will be closed.