Exemplo n.º 1
0
    // calculate what position and velocity we should send to peers who do not own the characters
    public void CalculatePositionAndVelocityToSend(ref Vector2 position, ref Vector2 velocity, ref float distToDestination)
    {
        // to save some bandwidth we're sending 2d vectors. y is calculated procedurally based on the ground height at the point you are standing on so isn't needed to be sent
        position.x = transform.position.x;
        position.y = transform.position.z;
        Vector3 velocity3d = new Vector3(_rvoController.newVelocity.x, 0f, _rvoController.newVelocity.z);

        Vector3 positionToDestinationXZ = GameUtils.SubXZ(_locomotion.Destination, transform.position);

        distToDestination = Mathf.Max(positionToDestinationXZ.magnitude - _locomotion.ArrivalThreshold, 0f);
        // check if our current rvo controller velocity is gonna make us overshoot the target
        if (velocity3d.magnitude * GetNetworkUpdateInterval() > distToDestination)
        {         // set our speed so we do not overshoot
            velocity3d = velocity3d.normalized * (distToDestination / GetNetworkUpdateInterval());
        }

        const float DirectionTolerance = 0.819f; // 0.819f == cos(35 degrees)
        const float StoppingTime       = 4f;     // seconds

        // if the character is not heading towards the destination, or the destination is far away then it's not gonna stop soon and the distance can be unlimited
        if (GameUtils.DotXZ(velocity3d.normalized, positionToDestinationXZ.normalized) < DirectionTolerance || // character is not traveling towards target (probably RVO related)
            distToDestination > velocity3d.magnitude * GetNetworkUpdateInterval() * StoppingTime)              // the destination is far away, so no stop is imminent
        {
            distToDestination = NetworkTransform.DistanceUnlimited;
        }

        // this section makes sure our velocity would not take us off the nav mesh
        Vector3 from           = transform.position;
        Vector3 targetPosition = AStarPathfindingUtils.CalculateExitPoint(ref from, from + velocity3d, _locomotion.Simulator, true);         // see if the target poition would cause us to exit the nav mesh

        float distToOriginalTargetSqr = GameUtils.GetDistSqXZ(from, from + velocity3d);
        float distToNewTargetSqr      = GameUtils.GetDistSqXZ(from, targetPosition);

        if (distToNewTargetSqr < distToOriginalTargetSqr)         // if the returned length is nearer, it means we hit an edge
        {
            const float NudgeIntoNavMeshDist = 0.1f;
            if (distToNewTargetSqr > NudgeIntoNavMeshDist * NudgeIntoNavMeshDist)
            {
                float distToNewTarget = Mathf.Sqrt(distToNewTargetSqr);
                // here we're moving targetPosition slightly back onto the nav mesh away from the nav mesh perimeter, this is to stop the character being moved slightly off mesh
                targetPosition = from + (((targetPosition - from) / distToNewTarget) * (distToNewTarget - NudgeIntoNavMeshDist));
            }
            else
            {
                targetPosition = from;                 // edge is very close, so just use the from position as the target position
            }
            velocity3d = targetPosition - transform.position;
        }
        velocity.x = velocity3d.x;
        velocity.y = velocity3d.z;

        if (!NetworkTransform.IsMovement(new Vector3(velocity3d.x, 0f, velocity3d.z))) // is no movement being sent
        {                                                                              // if we're sending a velocity of zero, we can have distance unlimited because there will be no movement anyway, so having distance unlimited means it can start moving quickly when a movement begins
            distToDestination = NetworkTransform.DistanceUnlimited;
        }
    }
Exemplo n.º 2
0
    // looks to see if updates are coming to a hard stoppage ahead
    private bool IsStopAhead(int update, float displayTime)
    {
        for (; update < _networkTransforms.Count; ++update)
        {
            NetworkTransform netTrans = _networkTransforms[update];
            if (displayTime < netTrans.time)
            {
                break;
            }

            // this update has reached its destination
            if (netTrans.hasDestinationBeenReached || !NetworkTransform.IsMovement(netTrans.correctVelocity))
            {
                return(true);
            }
        }
        return(false);
    }
Exemplo n.º 3
0
    // add a new network transform
    public void SetTransformInterpolated(Vector2 position, Vector2 velocity, Quaternion rotation, float distToDestination, double networkTime)
    {
        if (!allowNetworkUpdates || loopMode)         // for debugging
        {
            return;
        }

        if (_networkTransforms.Count > 0 && GetMostRecentUpdate().networkTime > networkTime) // this checks if we are receiving an update which is older than our most recent
        {
            return;                                                                          // we're not interested in out of order network updates
        }

        NetworkTransform temp = null;

        if (_networkTransforms.Count >= _numNetworkTransformHistory)         // we only keep a history of size _numNetworkTransformHistory
        {
            temp = _networkTransforms[0];

            temp.isFirstUsage = true;
            temp.hasTransformBeenFullyBlendedIn    = false;
            temp.havePredictionsBeenFullyCorrected = false;
            temp.isTransitionToNextReady           = false;
            temp.hasDestinationBeenReached         = false;

            // debugging
            temp.actualNextUpdateTime = -1f;
            temp.angleError           = -999f;
            temp.positionalError      = -1f;
            // debugging
        }
        else
        {
            temp = new NetworkTransform();
        }

        temp.time = Time.time;
        temp.predictedDistToDestination = temp.correctedDistToDestination = distToDestination;
        // we are unpacking the 2d vectors into 3d vectors, the y elements are actually the z elements - see OnSerializeView for packing
        temp.position          = new Vector3(position.x, 0f, position.y);
        temp.predictedVelocity = temp.correctVelocity = new Vector3(velocity.x, 0f, velocity.y);
        temp.rotation          = rotation;
        if (!_locomotion.ShouldIgnoreRotation)
        {
            temp.correctedRotation = temp.predictedRotation = NetworkTransform.IsMovement(temp.predictedVelocity) ? Quaternion.LookRotation(temp.predictedVelocity.normalized) : rotation;
        }
        else
        {
            temp.correctedRotation = temp.predictedRotation = rotation;
        }
        temp.networkTime = networkTime;

        temp.rotationPeriod = GetNetworkUpdateInterval();

        float notUsed = 0f;
        float positionBlendInTimeSetting = 0f;
        float rotationBlendInTimeSetting = 0f;

        CalculateBlendTimes(ref notUsed, ref positionBlendInTimeSetting, ref rotationBlendInTimeSetting);
        temp.positionBlendInTime = positionBlendInTimeSetting;
        temp.rotationBlendInTime = rotationBlendInTimeSetting;

        //  debugging ----------------------------------------------------------------------------------------------------------------------
        temp.extrapolatedPosition   = temp.position;
        temp.expectedNextUpdateTime = temp.time + GetNetworkUpdateInterval();
        if (_networkTransforms.Count > 0)
        {
            _networkTransforms[_networkTransforms.Count - 1].actualNextUpdateTime = Time.time;
            Vector3 predictedPosition = _networkTransforms[_networkTransforms.Count - 1].position + _networkTransforms[_networkTransforms.Count - 1].predictedVelocity;
            _networkTransforms[_networkTransforms.Count - 1].positionalError = GameUtils.GetDistXZ(predictedPosition, temp.position);
            float dot = GameUtils.DotXZ((temp.position - _networkTransforms[_networkTransforms.Count - 1].position).normalized, _networkTransforms[_networkTransforms.Count - 1].predictedVelocity.normalized);
            _networkTransforms[_networkTransforms.Count - 1].angleError = Mathf.Rad2Deg * Mathf.Acos(dot);
        }
        // -----------------------------------------------------------------------------------------------------------------------------------

        int _networkTransformsCount = _networkTransforms.Count;

        if (_networkTransformsCount >= _numNetworkTransformHistory)         // we only keep a history of size _numNetworkTransformHistory
        {
            for (int netTrans = 0; netTrans < _networkTransformsCount - 1; ++netTrans)
            {
                _networkTransforms[netTrans] = _networkTransforms[netTrans + 1];
            }
            _networkTransforms[_networkTransformsCount - 1] = temp;
        }
        else
        {
            _networkTransforms.Add(temp);
        }
    }