コード例 #1
0
    void AddManualPackage(Vector3 pos, Vector3 dir, double stateTime)
    {
        Projectile2DState newState = new Projectile2DState(stateTime, pos, dir);

        AddPacketToBuffer(newState);
        SortPacketBuffer();
    }
コード例 #2
0
    /// <summary>
    /// adds/inserts a packet t
    /// o a list of packages using the gameTime variable for sorting purposes
    /// </summary>
    /// <param name="packet"></param>
    void AddPacketToBufferSorted(Projectile2DState packet)
    {
        // always sort NEWEST ( highest gametime ) LAST
        if (m_PacketBuffer == null)
        {
            m_PacketBuffer = new List <Projectile2DState>();
        }

        int    insertIndex = 0;
        double previousIterationStateTime = 0;

        for (int i = 0; i < m_PacketBuffer.Count; i++)
        {
            if (previousIterationStateTime < packet.stateTime) // if packet is newer
            {
                insertIndex = i;
            }

            previousIterationStateTime = m_PacketBuffer[i].stateTime;
        }
        m_PacketBuffer.Insert(insertIndex, packet);
        //}
        //else
        //{
        //    // A < B ... no C
    }
コード例 #3
0
    /// <summary>
    /// Owner side collision detection, fixes ball offset
    /// </summary>
    /// <param name="collision"></param>
    void OnCollisionEnter(Collision collision)
    {
        // invert direction on collision
        foreach (ContactPoint contact in collision.contacts)
        {
            Debug.DrawRay(contact.point + Vector3.up, contact.normal, Color.red, 5);
            Vector3 N = contact.normal;

            N.Normalize();


            Vector3 D = Direction;

            Vector3 R = Reflect(D, N);

            // send a package to all clients that a bounce took place here!

            // make sure I remove Y
            R.y = 0;
            R.Normalize();


            // calc Overshoot and adjust ball position accordingly
            float collisionSphereRadius = 1.5f / 2f; // TODO: using collisionsphere size set in Collision method
            float overshoot             = collisionSphereRadius - (contact.point - transform.position).magnitude;

            // only correct the position of this object is heading TOWARD the wall
            // if the angle between NORMAL and R is less than 90 degrees. I can estimate that the object is already moving away from
            // the contact point
            float deltaNormalCurrentDirection = Vector3.Angle(contact.normal, Direction);

            if (deltaNormalCurrentDirection < 90)
            {
                return; // exit
            }
            if (PhotonNetwork.isMasterClient)
            {
                Direction = R;
            }

            Rigidbody rbdy = GetComponent <Rigidbody>();
            rbdy.velocity = Vector3.zero;

            Vector3 correctedPosition = transform.position + (Direction * overshoot);

            rbdy.MovePosition(correctedPosition);



            // Send custom packet to clients. With some luck it arrives
            if (PhotonNetwork.isMasterClient == false)
            {
                // I let the CLIENT add a package right after the collision, so that it is later on fooled into thinking the server orchestrated a bounce here.
                //AddManualPackage(correctedPosition, R, PhotonNetwork.time);
                Projectile2DState newPacket = new Projectile2DState(PhotonNetwork.time, correctedPosition, R, false);
                AddPacketToBuffer(newPacket);
                SortPacketBuffer();
            }
        }
    }
コード例 #4
0
    public void BallHit(Vector3 hitpos, Vector3 newDirection, double netTime)
    {
        if (MovementSpeed == 0)
        {
            AdjustMovementSpeed(+8.0f);
        }
        else
        {
            AdjustMovementSpeed(+2.5f);
        }

        Direction = newDirection;
        // add new keyframe
        Projectile2DState newKeyFrame = new Projectile2DState(netTime, hitpos, newDirection, false);

        AddPacketToBuffer(newKeyFrame);
    }
コード例 #5
0
    /// <summary>
    /// Returns the package immediatly before gameTime
    /// </summary>
    /// <param name="gameTime"></param>
    /// <param name="sortFirst"></param>
    /// <returns></returns>
    Projectile2DState GetPackageBefore(double gameTime, bool sortFirst = false)
    {
        if (sortFirst)
        {
            SortPacketBuffer();
        }

        Projectile2DState returnObject = m_PacketBuffer[0]; // set to first object

        // run down the buffer from OLDEST TO NEWEST, as soon as I hit a time that is BIGGEr I'm in bussiness
        for (int i = 0; i < m_PacketBuffer.Count; i++)
        {
            if (m_PacketBuffer[i].stateTime < gameTime) // as long as stored time < given time it's ok.
            {
                returnObject = m_PacketBuffer[i];
            }
        }
        return(returnObject);
    }
コード例 #6
0
    /// <summary>
    /// Updates local client version of the ball, mixing server data and locally simulated data
    /// </summary>
    void Update_ClientPredict_Lerp()
    {
        if (m_PacketBuffer.Count == 0)
        {
            return;
        }


        // Estimated Result given by server data
        Vector3           predictionResult = Vector3.zero;
        Projectile2DState lastPackage      = GetLastPackage();

        double timeSinceLastPackageState = PhotonNetwork.time - lastPackage.stateTime;

        predictionResult = CalculateProjectilePos(lastPackage.Position3() + Vector3.up * .5f, lastPackage.Direction3(), MovementSpeed, (float)timeSinceLastPackageState);// + Time.deltaTime);


        // Locally Simulated result
        Vector3 simulationResult = CalculateProjectilePos(transform.position, Direction, MovementSpeed, Time.deltaTime);


        Direction.y = 0;
        Direction.Normalize();

        // blend the 2 results
        float epsillon    = (predictionResult - simulationResult).magnitude;
        float maxEpsillon = 1f;

        Vector3 blendedPosition = Vector3.Lerp(simulationResult, predictionResult, epsillon / maxEpsillon);

        //Vector3 blendedDirection = Vector3.Lerp(Direction, lastPackage.Direction3(), epsillon / maxEpsillon); // to not blend yet

        transform.position = blendedPosition;
        Rigidbody rbdy = GetComponent <Rigidbody>();

        rbdy.velocity = Vector3.zero;



        Direction = lastPackage.Direction3();
        //rbdy.MovePosition(blendedPosition);
    }
コード例 #7
0
    // Network Code
    //------------
    void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
    {
        // SERVER SIDE , stream out projectile info
        if (PhotonNetwork.isMasterClient)
        {
            Projectile2DState newState = new Projectile2DState(PhotonNetwork.time, transform.position, Direction);
            if (stream.isWriting)
            {
                //Debug.LogWarning("Reading writing @" + PhotonNetwork.time);
                //Rigidbody rbdy = GetComponent<Rigidbody>();
                stream.SendNext(newState.stateTime);
                stream.SendNext(newState.Position);
                stream.SendNext(newState.Direction);
            }
        }
        // CLIENT SIDE
        else
        {
            if (stream.isReading)
            {
                //Debug.Log();

                //Debug.Log("Reading reading @" + PhotonNetwork.time);
                // receive packets and add them to the list of packets, ( then sort )
                Projectile2DState receivedState = new Projectile2DState();
                receivedState.stateTime      = (double)stream.ReceiveNext();
                receivedState.Position       = (Vector2)stream.ReceiveNext();
                receivedState.Direction      = (Vector2)stream.ReceiveNext();
                receivedState.ServerVerified = true;

                if (m_PacketBuffer == null)
                {
                    m_PacketBuffer = new List <Projectile2DState>();
                }

                AddPacketToBuffer(receivedState);
                SortPacketBuffer();
                CleanPacketBuffer(PhotonNetwork.time - 1f);  // remove old packets if possible
            }
        }
    }
コード例 #8
0
ファイル: BouncingProjectile.cs プロジェクト: TamaHobbit/DMV
    /// <summary>
    /// adds/inserts a packet t
    /// o a list of packages using the gameTime variable for sorting purposes
    /// </summary>
    /// <param name="packet"></param>
    void AddPacketToBufferSorted(Projectile2DState packet)
    {
        // always sort NEWEST ( highest gametime ) LAST
        if (m_PacketBuffer == null)
            m_PacketBuffer = new List<Projectile2DState>();

        int insertIndex = 0;
        double previousIterationStateTime = 0;
        for (int i = 0; i < m_PacketBuffer.Count; i++)
        {
            if (previousIterationStateTime < packet.stateTime) // if packet is newer
            {
                insertIndex = i;
            }

            previousIterationStateTime = m_PacketBuffer[i].stateTime;
        }
        m_PacketBuffer.Insert(insertIndex, packet);
         //}
                //else
                //{
                //    // A < B ... no C
         
    }
コード例 #9
0
ファイル: BouncingProjectile.cs プロジェクト: TamaHobbit/DMV
 /// <summary>
 /// Adds a packet to the bufferlist
 /// </summary>
 /// <param name="packet"></param>
 void AddPacketToBuffer(Projectile2DState packet)
 {
     m_PacketBuffer.Add(packet);
 }
コード例 #10
0
ファイル: BouncingProjectile.cs プロジェクト: TamaHobbit/DMV
 void AddManualPackage(Vector3 pos, Vector3 dir, double stateTime)
 {
     Projectile2DState newState = new Projectile2DState(stateTime, pos, dir);
     AddPacketToBuffer(newState);
     SortPacketBuffer();
 }
コード例 #11
0
ファイル: BouncingProjectile.cs プロジェクト: TamaHobbit/DMV
    // Network Code
    //------------
    void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) {

        // SERVER SIDE , stream out projectile info
        if (PhotonNetwork.isMasterClient)
        {

            Projectile2DState newState = new Projectile2DState( PhotonNetwork.time, transform.position, Direction);
            if (stream.isWriting)
            {
                //Debug.LogWarning("Reading writing @" + PhotonNetwork.time);
                //Rigidbody rbdy = GetComponent<Rigidbody>();
                stream.SendNext(newState.stateTime);
                stream.SendNext(newState.Position);
                stream.SendNext(newState.Direction);

            }
        }
        // CLIENT SIDE
        else
        {
            if (stream.isReading)
            {
                
                //Debug.Log();

                //Debug.Log("Reading reading @" + PhotonNetwork.time);
                // receive packets and add them to the list of packets, ( then sort )
                Projectile2DState receivedState = new Projectile2DState();
                receivedState.stateTime = (double)stream.ReceiveNext();
                receivedState.Position = (Vector2)stream.ReceiveNext();
                receivedState.Direction = (Vector2)stream.ReceiveNext();
                receivedState.ServerVerified = true;

                if (m_PacketBuffer == null)
                    m_PacketBuffer = new List<Projectile2DState>();

                AddPacketToBuffer(receivedState);
                SortPacketBuffer();
                CleanPacketBuffer( PhotonNetwork.time - 1f); // remove old packets if possible
            }
        }
    }
コード例 #12
0
ファイル: BouncingProjectile.cs プロジェクト: TamaHobbit/DMV
    /// <summary>
    /// Owner side collision detection, fixes ball offset
    /// </summary>
    /// <param name="collision"></param>
    void OnCollisionEnter(Collision collision)
    {
    // invert direction on collision
        foreach (ContactPoint contact in collision.contacts)
        {
            Debug.DrawRay(contact.point + Vector3.up, contact.normal, Color.red, 5);
            Vector3 N = contact.normal;

            N.Normalize();


            Vector3 D = Direction;

            Vector3 R = Reflect(D, N);

            // send a package to all clients that a bounce took place here!

            // make sure I remove Y
            R.y = 0;
            R.Normalize();


            // calc Overshoot and adjust ball position accordingly
            float collisionSphereRadius = 1.5f / 2f; // TODO: using collisionsphere size set in Collision method
            float overshoot = collisionSphereRadius - (contact.point - transform.position).magnitude;

            // only correct the position of this object is heading TOWARD the wall
            // if the angle between NORMAL and R is less than 90 degrees. I can estimate that the object is already moving away from
            // the contact point
            float deltaNormalCurrentDirection = Vector3.Angle(contact.normal, Direction);

            if (deltaNormalCurrentDirection < 90)
                return; // exit

            if (PhotonNetwork.isMasterClient)
            {
                Direction = R;

            }

            Rigidbody rbdy = GetComponent<Rigidbody>();
            rbdy.velocity = Vector3.zero;

            Vector3 correctedPosition = transform.position + (Direction * overshoot);
            
            rbdy.MovePosition(correctedPosition);

            
            
            // Send custom packet to clients. With some luck it arrives 
            if (PhotonNetwork.isMasterClient == false)
            {
                // I let the CLIENT add a package right after the collision, so that it is later on fooled into thinking the server orchestrated a bounce here.
                //AddManualPackage(correctedPosition, R, PhotonNetwork.time);
                Projectile2DState newPacket = new Projectile2DState(PhotonNetwork.time, correctedPosition, R, false);
                AddPacketToBuffer(newPacket);
                SortPacketBuffer();

            }
                
        }
        
    }
コード例 #13
0
ファイル: BouncingProjectile.cs プロジェクト: TamaHobbit/DMV
    void DrawPackageInfo(Projectile2DState pack, Color col) {

        Debug.DrawLine(pack.Position3() + Vector3.up, pack.Position3() + pack.Direction3() + Vector3.up , col, 1);
    }
コード例 #14
0
 void DrawPackageInfo(Projectile2DState pack, Color col)
 {
     Debug.DrawLine(pack.Position3() + Vector3.up, pack.Position3() + pack.Direction3() + Vector3.up, col, 1);
 }
コード例 #15
0
 /// <summary>
 /// Adds a packet to the bufferlist
 /// </summary>
 /// <param name="packet"></param>
 void AddPacketToBuffer(Projectile2DState packet)
 {
     m_PacketBuffer.Add(packet);
 }
コード例 #16
0
ファイル: BouncingProjectile.cs プロジェクト: TamaHobbit/DMV
    public void BallHit(Vector3 hitpos, Vector3 newDirection , double netTime)
    {

        if (MovementSpeed == 0)
            AdjustMovementSpeed(+8.0f);
        else AdjustMovementSpeed(+5f);

        Direction = newDirection;
        // add new keyframe
        Projectile2DState newKeyFrame = new Projectile2DState(netTime, hitpos, newDirection, false);
        AddPacketToBuffer(newKeyFrame);
    }
コード例 #17
0
ファイル: BouncingProjectile.cs プロジェクト: TamaHobbit/DMV
    void Update_ClientPredict() {

        // get most recent package and calculate position from there?
        if (m_PacketBuffer.Count > 0)
        {
                // init variables
            Projectile2DState currentPackage = GetPackageBefore( PhotonNetwork.time - ArticifialDelay);

            Rigidbody rbdy = GetComponent<Rigidbody>();

            Vector3 clientPos = transform.position; 
            Vector3 serverPos = currentPackage.Position3();

            //Vector3 clientDir = Direction;
            Vector3 serverDir = currentPackage.Direction3();

            
            double clientTime = PhotonNetwork.time - ArticifialDelay;
            double serverTime = currentPackage.stateTime;

            rbdy.velocity = Vector3.zero; // override unity's ridigbody

            Vector3 currentPos = clientPos;
            float dTime = Time.deltaTime;
            

            if(m_lastUsedPacket.stateTime.CompareTo(currentPackage.stateTime) == -1)
            {
                // new packet is used for the first time
                float packAge =(float)( clientTime - serverTime);


                // if collision is imminent, .. don't overwrite?
                // imminent = within packAge
                RaycastHit[] hitinfo = Physics.SphereCastAll(serverPos, .75f, serverDir, packAge * MovementSpeed, LayerMask.GetMask("WorldCollision") );

                if (hitinfo.Length != 0) {
                    
                    // this means a hit would have happened between ServerTime and Now ,
                    // todo: predict clientpos further, or leave it like this
                    Debug.LogWarning("predicted a hit");
                }
                else currentPos = CalculateProjectilePos(serverPos, serverDir, MovementSpeed, packAge);

                //dTime = (float)(clientTime - serverTime); // <--- THIS IS WRONG!, this is the time to the current frame!
                // calculate where the projecitle SHOULD BE!
            }

            // prediction code:
            Vector3 nextBallPos = CalculateProjectilePos(currentPos, Direction, MovementSpeed, dTime);

            // Using rigidbody;'s move, I get physix calculations for everything I do, so this is prefered
            rbdy.MovePosition(nextBallPos);

            nextPosition = nextBallPos;
            previousPosition = currentPos;
            m_lastUsedPacket = currentPackage;
            
        }
    }
コード例 #18
0
    void Update_ClientPredict()
    {
        // get most recent package and calculate position from there?
        if (m_PacketBuffer.Count > 0)
        {
            // init variables
            Projectile2DState currentPackage = GetPackageBefore(PhotonNetwork.time - ArticifialDelay);

            Rigidbody rbdy = GetComponent <Rigidbody>();

            Vector3 clientPos = transform.position;
            Vector3 serverPos = currentPackage.Position3();

            //Vector3 clientDir = Direction;
            Vector3 serverDir = currentPackage.Direction3();


            double clientTime = PhotonNetwork.time - ArticifialDelay;
            double serverTime = currentPackage.stateTime;

            rbdy.velocity = Vector3.zero; // override unity's ridigbody

            Vector3 currentPos = clientPos;
            float   dTime      = Time.deltaTime;


            if (m_lastUsedPacket.stateTime.CompareTo(currentPackage.stateTime) == -1)
            {
                // new packet is used for the first time
                float packAge = (float)(clientTime - serverTime);


                // if collision is imminent, .. don't overwrite?
                // imminent = within packAge
                RaycastHit[] hitinfo = Physics.SphereCastAll(serverPos, .75f, serverDir, packAge * MovementSpeed, LayerMask.GetMask("WorldCollision"));

                if (hitinfo.Length != 0)
                {
                    // this means a hit would have happened between ServerTime and Now ,
                    // todo: predict clientpos further, or leave it like this
                    Debug.LogWarning("predicted a hit");
                }
                else
                {
                    currentPos = CalculateProjectilePos(serverPos, serverDir, MovementSpeed, packAge);
                }

                //dTime = (float)(clientTime - serverTime); // <--- THIS IS WRONG!, this is the time to the current frame!
                // calculate where the projecitle SHOULD BE!
            }

            // prediction code:
            Vector3 nextBallPos = CalculateProjectilePos(currentPos, Direction, MovementSpeed, dTime);

            // Using rigidbody;'s move, I get physix calculations for everything I do, so this is prefered
            rbdy.MovePosition(nextBallPos);

            nextPosition     = nextBallPos;
            previousPosition = currentPos;
            m_lastUsedPacket = currentPackage;
        }
    }