Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Join us on March 30, 2023, between 5 am & 1 pm EST, in the Performance Profiling Dev Blitz Day 2023 - Q&A forum and Discord where you can connect with our teams behind the Memory and CPU Profilers.
    Dismiss Notice

Question SphereCast result differs between Client and Server

Discussion in 'Physics for ECS' started by RichardWepner, Jun 23, 2022.

  1. RichardWepner

    RichardWepner

    Joined:
    May 29, 2013
    Posts:
    31
    The game I'm trying to implement is basically using Snowboarding as the main mechanic. I'm trying to implement this using DOTS, Netcode for DOTS, and Unity Physics.

    Since at the time I started this, Unity Physics didn't work well together with Netcode, I started to implement the game mechanics manually only using Unity Physics for physic queries. The previous approach was so cheap that it was bound to break at some point. (Put simple, I adjusted the position, did a
    SphereOverlap
    , and resolved the first collision - yes, bound to break.)

    I attempted to replace this with a more sophisticated approach: to a
    SphereCast
    /
    SphereCastAll
    , adjust the position and velocity on first collision, and repeat.
    With
    SphereCastAll
    I run into problems with the environment that I currently generate, this is composed out of segments, and if the player is exactly above the very edge between 2 segments, 4 collisions are detected, all with a
    Fraction
    of
    0
    . I tried to see if I might be able to discard the collisions that really don't matter, but I didn't find a way to get the surface data to discard any of the collisions.
    With
    SphereCast
    , there's also always just a single collision found at
    Friction
    0
    , meaning that the player isn't moving forward.

    In the code, the following is supposed to adjust the velocity:
    Code (CSharp):
    1. var normalPart = normalVelocityDot * hit.SurfaceNormal;
    2. velocity.Value -= normalPart;
    3.  
    where
    math.normalize(velocity.Value)
    is the direction of the cast, and

    math.length(velocity.Value) * deltaTime * remainingPercentage
    is the length. After this, the velocity should be parallel to the ground, but still the collision occurs basically at the start position of the cast.

    If I reduce the radius of the
    SphereCast
    just minimally, it mostly works, but due to the wrong size, the sphere can be positioned into the environment, which can lead the player to move into the ground. Just adjusting the casting position upwards could lead to issues at walls causing the player to be able to slide up on walls.
    I didn't yet try to first do a
    SphereCast
    downwards, get the normal, calculate the velocity alongside the floor, and use that instead of the above shown adjusted velocity. I'm actually afraid that this will again lead to the same issue I already have.

    Besides that, I could give the regular Unity Physics (for DOTS) a try, but there I would need to figure out how to deal with the "realistic" physics to end up with a physics model that's suitable for the game. This includes preventing players from sliding down the hill sideways, "glueing" players and projectiles to the ground, etc.


    Is there anything I might do (obviously) wrong with my approach? Did I miss something? Does maybe someone have a better approach for this?
     
  2. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    2,088
    Unity Physics is not deterministic, hence not usable for networked/synchronized gameplay. For visuals it‘s fine if those physics do not influence gameplay (ie block bullets, cause damage, etc.).

    Your options are either DOTS physics or the Havok package. Both are deterministic but you‘ll have to retweak the feel of the gameplay/interactions from scratch.
     
  3. RichardWepner

    RichardWepner

    Joined:
    May 29, 2013
    Posts:
    31
    Well, by "Unity Physics" I was referring to the one that's used with DOTS.

    Edit: Unity Physics is actually the official name, see the official documentation.
     
    Last edited: Jun 23, 2022
  4. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    2,088
    Is this even a networking issue? I‘m reading it again and must have assumed you have synch issues but it‘s really about the movement itself right? Pretty difficult to make suggestions without looking at the project. But it feels like the kind of project that the Kinematic character controller could help with: https://assetstore.unity.com/packages/tools/physics/rival-dots-character-controller-195567

    As long as you want to keep tweaking the player behaviour manually.
     
  5. RichardWepner

    RichardWepner

    Joined:
    May 29, 2013
    Posts:
    31
    It's unlikely to be a networking issue, but I'm implementing this in a project that's using Netcode (and ultimately, it needs to work inside a networked project).

    I'd like to take a look at how the rival character controller works, but it costs $80, and I don't even know if I would be able to implement a Snowboarding mechanic with that one.

    I also don't mind if I use a different approach, as long as it will work.
     
  6. RichardWepner

    RichardWepner

    Joined:
    May 29, 2013
    Posts:
    31
    To be honest, I just noticed that the title of this thread only contains one part of the last attempt I made while writing this, and it isn't even the part that desperately needs to be fixed. (And it seems like I can't edit the title anymore. x.x)

    With the `SphereCast`, the server position didn't change at all, but the client position did seem to change. Since the client would receive a new state from the server and reset to that, the client only had as much distance from the actual server position as he would move with the currently stored velocity value.

    Okay, besides that I also took a look at a "UnityDotsCharacterController" for DOTS. This isn't precisely what I need in my case, but there should be similarities, most notably the movement over the ground and the collision detection used there. There I noticed that a
    ColliderDistance
    was used to determine how much the collider was penetrating other objects in order to adjust the position. Adjusting my code to this approach didn't help, though, since I still had the same issues of the player sometimes sinking into the geometry (difficult to say what causes it).

    One big difference is still (if I'm not mistaken), that this CharacterController just checks for penetrations at the movement steps target position without fully doing the collider cast, but something like this would yield tunneling as soon as objects move to fast. (I assume this could happen in my game: a projectile moving at 50 m/s results in a 1m movement step if the refresh rate is 50 FPS.)


    I'll give the regular physics simulation (with adjustments for the gameplay) another try, even though I still don't have high hopes. But I seemingly tried every other option. (The code involved is rather simple, so even though I can't guarantee not to have no mistakes on my side, I'm still pretty confident about it.)