Exemplo n.º 1
0
    public void DrawActorDebugGUI(VoosActor actor)
    {
        using (new Util.GUILayoutFrobArea(actor.transform.position, 100, 500))
        {
            PhotonView photonView = PhotonView.Get(actor);
            if (photonView == null)
            {
                return;
            }
            PlayerBody playerBody = actor.GetPlayerBody();
            //string pbodyInfo = playerBody == null ? "" : $"Claimed? {playerBody.IsClaimed()} ..play mode? {playerBody.GetIsClaimerPlaying()}";
            string color         = photonView.isMine ? "yellow" : "grey";
            string hash          = actor.GetName().Substring(0, 9);
            bool   locked        = actor.IsLockedByAnother() || actor.IsLockWantedLocally();
            string lockingString = locked ? " LOCKED" : "";
            string lastPos       = actor.unrel == null ? "" : actor.unrel.lastPosition.x.ToFourDecimalPlaces();
            GUILayout.Label($@"<color={color}>{actor.GetDisplayName()}
rot: {actor.GetRotation().ToFourDecimalPlaces()}
last unrel: {actor.lastUnreliableUpdateTime}
lastPX: {lastPos}</color>".Trim());
            GUILayout.Toggle(actor.GetReplicantCatchUpMode(), "Catchup?");
            actor.debug = GUILayout.Toggle(actor.debug, "Debug");
            // owner: {photonView.ownerId}{lockingString}
            // {hash} view {actor.reliablePhotonView.viewID}
            // X: {actor.transform.position.x.ToFourDecimalPlaces()}
            // lastRBMPX: {actor.lastRBMovedPos.x.ToFourDecimalPlaces()}
        }
    }
    void FixedUpdate()
    {
        foreach (KeyValuePair <short, NetworkedActor> na in actors)
        {
            VoosActor va = na.Value.actor;
            if (va != null && !va.reliablePhotonView.isMine && !va.IsParented())
            {
                Rigidbody rb        = va.GetComponent <Rigidbody>();
                bool      isDynamic = rb != null && va.GetEnablePhysics();

                Vector3    pos = rb != null ? rb.position : va.transform.position;
                Quaternion rot = rb != null ? rb.rotation : va.transform.rotation;

                if (!isDynamic || va.GetReplicantCatchUpMode())
                {
                    // Kinematic or non-RB. Lerp it.
                    Quaternion lerpedRot = Quaternion.Lerp(rot, na.Value.lastRotation, Mathf.Clamp01(Time.deltaTime * 5));
                    var        damped    = Vector3.SmoothDamp(pos, na.Value.lastPosition,
                                                              ref na.Value.posDampVelocity, 0.2f);

                    va.ForceReplicantPosition(damped);
                    va.ForceReplicantRotation(lerpedRot);
                }
                else
                {
                    rb.angularVelocity *= 0.9f;

                    if (!SnapRigidbodyOnRecv)
                    {
                        // Let physics simulate the position with our corrective velocity,
                        // but we still lerp the rotation.
                        Quaternion lerpedRot = Quaternion.Lerp(rot, na.Value.lastRotation, Mathf.Clamp01(Time.deltaTime * 5));
                        rb.rotation = lerpedRot;
                    }
                }
            }
        }
    }
    void Deserialize(byte[] bytes, int senderId)
    {
        VoosNetworkTypes.ShortToBytes stb = new VoosNetworkTypes.ShortToBytes();
        VoosNetworkTypes.UintToBytes  utb = new VoosNetworkTypes.UintToBytes();

        if (bytes.Length < 6)
        {
            return;
        }

        stb.byte0 = bytes[0];
        stb.byte1 = bytes[1];
        short positionCount = stb.data;

        utb.byte0 = bytes[1];
        utb.byte1 = bytes[2];
        utb.byte2 = bytes[3];
        utb.byte3 = 0;
        float timestamp = VoosNetworkTypes.DecompressFloatFromUint24(utb.data);

        if (bytes.Length < 5 + positionCount * size)
        {
            return;
        }
        for (int i = 0; i < positionCount; i++)
        {
            int offset = 5 + i * size;
            /// View Id
            stb.byte0 = bytes[offset];
            stb.byte1 = bytes[offset + 1];
            offset   += 2;

            short viewId = stb.data;
            if (actors.ContainsKey(viewId))
            {
                NetworkedActor na = actors[viewId];
                VoosActor      va = na.actor;

                if (va == null)
                {
                    diag.numNullActorEntries++;
                }
                if (va != null && va.reliablePhotonView.ownerId != senderId)
                {
                    diag.numSenderOwnerMismatches++;
                }

                if (va != null && va.reliablePhotonView.ownerId == senderId)
                {
                    va.lastUnreliableUpdateTime = Time.realtimeSinceStartup;
                    va.unrel = na;

                    float timeDelta = Mathf.Clamp(timestamp - na.lastRecvTimestamp, 0.01f, maxTimeDelta);
                    na.lastRecvTimestamp = timestamp;

                    UnreliableBitmask mask = (UnreliableBitmask)bytes[offset];
                    offset += 1;

                    Vector3 oldP = na.lastPosition;
                    /// Local Position
                    utb.byte0         = bytes[offset];
                    utb.byte1         = bytes[offset + 1];
                    utb.byte2         = bytes[offset + 2];
                    utb.byte3         = 0;
                    na.lastPosition.x = VoosNetworkTypes.DecompressFloatFromUint24(utb.data);
                    utb.byte0         = bytes[offset + 3];
                    utb.byte1         = bytes[offset + 4];
                    utb.byte2         = bytes[offset + 5];
                    utb.byte3         = 0;
                    na.lastPosition.y = VoosNetworkTypes.DecompressFloatFromUint24(utb.data);
                    utb.byte0         = bytes[offset + 6];
                    utb.byte1         = bytes[offset + 7];
                    utb.byte2         = bytes[offset + 8];
                    utb.byte3         = 0;
                    offset           += 9;
                    na.lastPosition.z = VoosNetworkTypes.DecompressFloatFromUint24(utb.data);
                    Vector3 predictionError = na.lastPosition - va.transform.position;

                    Quaternion oldQ = na.lastRotation;

                    // Full precision rotation for static
                    var   ftb = new VoosNetworkTypes.FloatToBytes();
                    float x   = ftb.DeserializeFrom(bytes, ref offset);
                    float y   = ftb.DeserializeFrom(bytes, ref offset);
                    float z   = ftb.DeserializeFrom(bytes, ref offset);
                    float w   = ftb.DeserializeFrom(bytes, ref offset);
                    na.lastRotation = new Quaternion(x, y, z, w);

                    /// Color
                    Color32 c = new Color32();
                    c.r     = bytes[offset];
                    c.g     = bytes[offset + 1];
                    c.b     = bytes[offset + 2];
                    c.a     = bytes[offset + 3];
                    offset += 4;
                    va.SetTint(c);

                    /// Linear V
                    utb.byte0           = bytes[offset];
                    utb.byte1           = bytes[offset + 1];
                    utb.byte2           = bytes[offset + 2];
                    utb.byte3           = 0;
                    na.linearVelocity.x = VoosNetworkTypes.DecompressFloatFromUint24(utb.data);
                    utb.byte0           = bytes[offset + 3];
                    utb.byte1           = bytes[offset + 4];
                    utb.byte2           = bytes[offset + 5];
                    utb.byte3           = 0;
                    na.linearVelocity.y = VoosNetworkTypes.DecompressFloatFromUint24(utb.data);
                    utb.byte0           = bytes[offset + 6];
                    utb.byte1           = bytes[offset + 7];
                    utb.byte2           = bytes[offset + 8];
                    utb.byte3           = 0;
                    na.linearVelocity.z = VoosNetworkTypes.DecompressFloatFromUint24(utb.data);

                    Rigidbody rb        = va.GetComponent <Rigidbody>();
                    bool      isDynamic = rb != null && va.GetEnablePhysics();

                    // Hard Snap if the teleport flag is on. Otherwise we smoothly interpolate.
                    if ((mask & UnreliableBitmask.Teleport) == UnreliableBitmask.Teleport)
                    {
                        predictionError       = Vector3.zero;
                        va.transform.position = na.lastPosition;
                        va.transform.rotation = na.lastRotation;

                        if (rb != null)
                        {
                            rb.velocity        = Vector3.zero;
                            rb.angularVelocity = Vector3.zero;
                        }
                    }

                    if (va.IsParented())
                    {
                        continue;
                    }

                    if (isDynamic)
                    {
                        if (SnapRigidbodyOnRecv)
                        {
                            rb.velocity = na.linearVelocity;
                            rb.MovePosition(na.lastPosition);
                            rb.MoveRotation(na.lastRotation);
                        }
                        else
                        {
                            const float catchUpEnterThresh = 1f;
                            const float catchUpExitThresh  = 0.5f;
                            float       errorDist          = predictionError.magnitude;
                            if (!va.GetReplicantCatchUpMode())
                            {
                                if (errorDist > catchUpEnterThresh)
                                {
                                    va.SetReplicantCatchUpMode(true);
                                }
                            }
                            else
                            {
                                if (va.debug)
                                {
                                    Util.Log($"in catch up mode... err dist: {errorDist}");
                                }
                                if (errorDist < catchUpExitThresh)
                                {
                                    va.SetReplicantCatchUpMode(false);
                                }
                            }

                            if (va.GetReplicantCatchUpMode())
                            {
                                // Let the fixed update directly lerp this.
                            }
                            else
                            {
                                // Best-effort corrective velocity only.
                                // TODO expose some tunable error -> correction velocity parameter?
                                rb.velocity = na.linearVelocity + predictionError;
                            }
                        }
                    }
                }
            }
            else
            {
                diag.numUnknownViewIds++;
            }
        }
    }