Beispiel #1
0
        /// <summary>
        /// This is the weapon fire code created for this example. It instantiates a cosmetic (not network synced) projectile.
        /// For a real project you should considered using pooled objects for projectiles.
        /// </summary>
        private void FireBullet(Frame frame, PlayerFireCustomMsg msg)
        {
            Vector3    originPos;
            Quaternion originRot;

            originPos = originGO.transform.position;
            originRot = originGO.transform.rotation;

            GameObject projGO = (projPoolId > -1) ?
                                Pool.Spawn(projPoolId, originPos, originRot, 3).gameObject :
                                CreatePlaceholderProjectile(originPos, originRot, false);

            //Rigidbody rb = projGO.GetComponent<Rigidbody>() ?? projGO.AddComponent<Rigidbody>();
            Rigidbody      rb      = projGO.GetComponent <Rigidbody>();
            INstProjectile nstProj = projGO.GetComponent <INstProjectile>();

            if (nstProj != null)
            {
                nstProj.OwnerNst = nst;
            }

            // This needs the projectile to have a RB, so add one if it is missing
            if (rb == null)
            {
                rb            = projGO.AddComponent <Rigidbody>();
                rb.useGravity = false;
            }

            rb.velocity = projGO.transform.forward * projVelocity;

            // Changes color to color sent over the network as an example of how to use the Custom Message
            projGO.GetComponentInChildren <MeshRenderer>().material.color = msg.color;
        }
Beispiel #2
0
        /// <summary>
        /// Player with local authority fires by calling this. This tells the NST to create a custom message and attach your data to it.
        /// </summary>
        /// <param name="wid"></param>
        public void PlayerFire()
        {
            PlayerFireCustomMsg customMsg = new PlayerFireCustomMsg
            {
                weaponId = (byte)weaponId,
                color    = new Color(Random.value,
                                     Random.value, Random.value),
            };

            nst.SendCustomEvent(customMsg);
        }
Beispiel #3
0
        /// <summary>
        /// Player with local authority fires by calling this. This tells the NST to create a custom message and attach your data to it.
        /// </summary>
        /// <param name="wid"></param>
        public void PlayerFire()
        {
            PlayerFireCustomMsg customMsg = new PlayerFireCustomMsg
            {
                weaponId = (byte)weaponId,
                color    = new Color(Random.value,
                                     Random.value, Random.value),
            };

            NetworkSyncTransform.SendCustomEventSimple(customMsg);
        }
Beispiel #4
0
    /// <summary>
    /// When a custom message is received, the OnCustomMsgRcvEvent is fired. Note that the rotations will only be correct if you have the NST set to update
    /// rotations on events. If it is set to 'changes only' these rotations values will be zero.
    /// </summary>
    private static void OnCustomMsgRcv(NetworkConnection ownerConn, byte[] bytearray, NetworkSyncTransform shooterNst, Vector3 pos, List <GenericX> positions, List <GenericX> rotations)
    {
        //For this example we fired locally already when the custom message was sent (with OnCustomMsgSend). Firing again here on the local player would cause repeat fire events.
        //Note however that code for the local player can be added here to sync the projectile with the server, by adding a projectileID to your custom events.

        Weapon wpn = shooterNst.GetComponent <Weapon>();

        PlayerFireCustomMsg weaponFireMsg = bytearray.DeserializeToStruct <PlayerFireCustomMsg>();

        if ((WeaponType)weaponFireMsg.weaponId == WeaponType.Bullet)
        {
            if (!shooterNst.isLocalPlayer)
            {
                wpn.FireBullet(pos, rotations[0], weaponFireMsg);
            }
        }

        // Hitscan arrive on server/other clients

        else if ((WeaponType)weaponFireMsg.weaponId == WeaponType.Hitscan)
        {
            //DebugText.Log(weaponFireMsg.hitmask.PrintBitMask() + " RCV " + (WeaponType)weaponFireMsg.weaponId);
            uint confirmedHitmask = 0;

            // Draw the graphic if this isn't the local player
            if (!shooterNst.isLocalPlayer)
            {
                wpn.DrawRay(pos, rotations[0]);
            }

            // Server needs to test if this was a hit.
            if (NetworkServer.active)
            {
                for (int i = 0; i < 32; i++)
                {
                    if (weaponFireMsg.hitmask.GetBitInMask(i) == false)
                    {
                        continue;
                    }

                    NetworkSyncTransform hitNst = NetworkSyncTransform.GetNstFromId((uint)i);
                    bool hit = hitNst.TestHitscanAgainstRewind(ownerConn, new Ray(pos, (Quaternion)rotations[0] * Vector3.forward));

                    if (hit)
                    {
                        ((int)hitNst.NstId).SetBitInMask(ref confirmedHitmask, true);
                    }
                }
                DebugText.Log("Rewind Confirmation Mask : \n" + confirmedHitmask.PrintBitMask(), true);
            }
        }
    }
Beispiel #5
0
    // it is advisable to create a reusable byte array of the size you need to avoid GC by creating 'new' every time.
    //private static byte[] reusablebyte = new byte[1];

    /// <summary>
    /// This is the weapon fire code created for this example. It just creates a basic non-synced projectile.
    /// </summary>
    private void FireBullet(Vector3 pos, Quaternion rot, PlayerFireCustomMsg msg)
    {
        GameObject bullet = Instantiate(bulletPrefab);
        Rigidbody  rb     = bullet.GetComponent <Rigidbody>();

        bullet.transform.position = pos;
        bullet.transform.rotation = rot;
        bullet.GetComponentInChildren <MeshRenderer>().material.color = msg.color;

        Destroy(bullet, 1f);

        rb.velocity = bullet.transform.forward * 10;
    }
Beispiel #6
0
    /// <summary>
    /// This is the secondary weapon fire code created for this example. It just creates a basic non-synced projectile.
    /// </summary>
    private void FireMine(Vector3 pos, Quaternion rot, PlayerFireCustomMsg msg)
    {
        Debug.DrawRay(pos, rot * Vector3.forward * 10, Color.red, .5f, true);

        GameObject bullet = Instantiate(minePrefab);
        Rigidbody  rb     = bullet.GetComponent <Rigidbody>();

        bullet.transform.position = pos;
        bullet.transform.rotation = turret.transform.parent.rotation * rot;
        bullet.GetComponentInChildren <MeshRenderer>().material.color = msg.color;

        Destroy(bullet, 2f);

        rb.velocity = bullet.transform.forward * 5;
    }
Beispiel #7
0
        /// <summary>
        /// OnCustomMsgSndEvent fires on the originating client when a custom event is sent. The position and rotation information will contain the same
        /// lossy rounding errors/ranges that are being sent to the network. Useful for ensuring that your local events use the exact same pos/rot data
        /// the server and clients will be using (such as projectile vectors).
        /// </summary>
        public void OnSnd(Frame frame)
        {
            if (frame.updateType != UpdateType.Cust_Msg)
            {
                return;
            }

            PlayerFireCustomMsg weaponFireMsg = frame.customData.DeserializeToStruct <PlayerFireCustomMsg>();

            if (weaponFireMsg.weaponId != weaponId)
            {
                return;
            }

            FireBullet(frame, weaponFireMsg);
        }
Beispiel #8
0
    /// <summary>
    /// OnCustomMsgSndEvent fires on the originating client when a custom event is sent. The position and rotation information will contain the same
    /// lossy rounding errors/ranges that are being sent to the network. Useful for ensuring that your local events use the exact same pos/rot data
    /// the server and clients will be using (such as projectile vectors).
    /// </summary>
    /// <param name="rootPos">Lossy position after compression - exactly what is sent.</param>
    /// <param name="rotations">Lossy rotation after compression - exactly what is sent.</param>
    private static void OnCustomMsgSnd(NetworkConnection ownerConn, byte[] bytearray, NetworkSyncTransform nst, Vector3 rootPos, List <GenericX> positions, List <GenericX> rotations)
    {
        Weapon wpn = nst.GetComponent <Weapon>();

        PlayerFireCustomMsg weaponFireMsg = bytearray.DeserializeToStruct <PlayerFireCustomMsg>();

        if (weaponFireMsg.weaponId == (byte)WeaponType.Bullet)
        {
            wpn.FireBullet(rootPos, rotations[0], weaponFireMsg);
        }

        else if (weaponFireMsg.weaponId == (byte)WeaponType.Mine)
        {
            wpn.FireMine(wpn.turret.transform.position, rotations[1], weaponFireMsg);
        }
    }
Beispiel #9
0
    /// <summary>
    /// When a custom message is taken from the buffer and applied for interpolation, the OnCustomMsgRcvEvent is fired. Note that the rotations
    /// will only be correct if you have the NST set to update rotations on events. If it is set to 'changes only' these rotations values will be zero.
    /// </summary>
    private static void OnCustomMsgApply(NetworkConnection ownerConn, byte[] bytearray, NetworkSyncTransform nst, Vector3 pos, List <GenericX> positions, List <GenericX> rotations)
    {
        Weapon wpn = nst.GetComponent <Weapon>();

        PlayerFireCustomMsg weaponFireMsg = bytearray.DeserializeToStruct <PlayerFireCustomMsg>();

        if (nst == NetworkSyncTransform.lclNST)
        {
            return;
        }

        if (weaponFireMsg.weaponId == (byte)WeaponType.Mine)
        {
            wpn.FireMine(wpn.turret.transform.position, rotations[1], weaponFireMsg);
        }
    }
Beispiel #10
0
    /// <summary>
    /// Player with local authority fires by calling this. This tells the NST to create a custom message and attach your data to it.
    /// </summary>
    /// <param name="wid"></param>
    public void PlayerFire(WeaponType w)
    {
        int  hitId   = 0;
        uint hitmask = 0;

        if (w == WeaponType.Hitscan)
        {
            hitmask = CastRay(transform.position, transform.rotation, out hitId);
        }

        PlayerFireCustomMsg customMsg = new PlayerFireCustomMsg
        {
            weaponId = (byte)w,
            color    = new Color(Random.value,
                                 Random.value, Random.value), hitmask = hitmask
        };

        NetworkSyncTransform.SendCustomEventSimple(customMsg);
    }
Beispiel #11
0
        /// <summary>
        /// This is the weapon fire code created for this example. It instantiates a cosmetic (not network synced) projectile.
        /// For a real project you should considered using pooled objects for projectiles.
        /// </summary>
        private void FireBullet(Frame frame, PlayerFireCustomMsg msg)
        {
            Vector3    originPos;
            Quaternion originRot;

            originPos = originGO.transform.position;
            originRot = originGO.transform.rotation;

            Pool poolProj = Pool.Spawn(projPrefab, originPos, originRot, lifespanSecs);

            INstProjectile nstProj = poolProj.gameObject.GetComponent <INstProjectile>();

            if (nstProj != null)
            {
                nstProj.OwnerNst = nst;
            }

            poolProj.rb.velocity = poolProj.gameObject.transform.forward * projVelocity;

            // Changes color to color sent over the network as an example of how to use the Custom Message
            poolProj.GetComponentInChildren <MeshRenderer>().material.color = msg.color;
        }
Beispiel #12
0
        /// <summary>
        /// When a custom message is taken from the buffer and applied for interpolation, the OnCustomMsgRcvEvent is fired. Note that the rotations
        /// will only be correct if you have the NST set to update rotations on events. If it is set to 'changes only' these rotations values will be zero.
        /// </summary>
        public void OnEndInterpolate(Frame frame)
        {
            if (frame.updateType != UpdateType.Cust_Msg)
            {
                return;
            }

            // TODO: find a way to deserialize this only once
            PlayerFireCustomMsg weaponFireMsg = frame.customData.DeserializeToStruct <PlayerFireCustomMsg>();

            if (weaponFireMsg.weaponId != weaponId)
            {
                return;
            }

            // Don't call the fire graphics if this is the owner client - it already fired on send.
            if (frame.nst.na.IsLocalPlayer)
            {
                return;
            }

            FireBullet(frame, weaponFireMsg);
        }