It's time for some shooting! You might have noticed that the shooting action is not synced. In this section, you will add a remote event to the Player Prefab to sync player actions.
Remote Event Agent
Select the Player Prefab. Click the Add Component button and Search "Agent", select Remote Event Agent to attach it to the Player GameObject.
Click on the Add Remote Event button and set the Event Name to "fire".
The Event name is used to find and trigger event across different network. One Remote Event Agent cannot have remote events that have the same name.
The SWNetwork Remote Events are similar to the Unity events. You can invoke them in scripts. You can add listeners to them to handle the events. However, SWNetwork Remote Events when invoked will be triggered on all the remote duplicates.
You need to update the PlayerWeapon.cs script to invoke and handle the "fire" event.
Add two properties: networkId, and remoteEventAgent.
Only the source Player GameObject should receive user inputs, we can use the IsMine property of NetworkID to find out if the Player GameObject is the source GameObject.
Update the fireBullet() method to invoke the "fire" event. We used SWNetworkMessage to send the bullet launch position(vector3) and aim direction (vector3) along with the "fire" event.
Implement the Event Handler method. We used PopVector3() method on the SWNetworkMessage object to obtain the launch position and aim direction of the fire remote event.
publicvoidRemoteFire(SWNetworkMessage msg) {Vector3 position =msg.PopVector3();Vector3 direction =msg.PopVector3();gun.fireBullet(position, direction); }
The final version of PlayerWeapon.cs script should look like.
usingUnityEngine;usingSWNetwork;publicclassPlayerWeapon:MonoBehaviour{ // aimable layerspublicLayerMask layerMask;privateVector3 currentLookTarget =Vector3.zero;publicGun gun; // launch position of bulletspublicTransform launchPosition;NetworkID networkId;RemoteEventAgent remoteEventAgent;privatevoidStart() { networkId =GetComponent<NetworkID>(); remoteEventAgent =gameObject.GetComponent<RemoteEventAgent>(); }voidFixedUpdate() {if (networkId.IsMine) { // find player's cursor position in the environmentRaycastHit hit;Ray ray =Camera.main.ScreenPointToRay(Input.mousePosition);Debug.DrawRay(ray.origin,ray.direction*1000,Color.green);if (Physics.Raycast(ray,out hit,1000, layerMask,QueryTriggerInteraction.Ignore)) {if (hit.point!= currentLookTarget) { currentLookTarget =hit.point; } } // ignore cursor position's y value.Vector3 targetPosition =newVector3(hit.point.x,transform.position.y,hit.point.z); // calculate player's new rotationQuaternion rotation =Quaternion.LookRotation(targetPosition -transform.position); // lerptransform.rotation=Quaternion.Lerp(transform.rotation, rotation,Time.deltaTime*10.0f); } }voidUpdate() {if (networkId.IsMine) { // get mouse inputsif (Input.GetMouseButtonDown(0)) { // 0.5 seconds interval between shotsif (!IsInvoking("FireBullet")) {InvokeRepeating("FireBullet",0f,0.5f); } }if (Input.GetMouseButtonUp(0)) {CancelInvoke("FireBullet"); } } }voidFireBullet() {SWNetworkMessage msg =newSWNetworkMessage();msg.Push(launchPosition.position);msg.Push(transform.forward);remoteEventAgent.Invoke("fire", msg); }publicvoidRemoteFire(SWNetworkMessage msg) {Vector3 position =msg.PopVector3();Vector3 direction =msg.PopVector3();gun.FireBullet(position, direction); }}
Add a listener to the "fire" event. Make sure to select the RemoteFire() method under the Dynamic Parameter Section of the methods list.
Make sure you applied the change to the Player Prefab.
Double check if the player prefab has been saved correctly by inspecting the Player prefab in the /Assets/prefabs folder. Make sure the RemoteEventAgent is saved and the prefab is enabled.
Play
Make sure you disabled the Player GameObject in the Hierarchy.
You can follow the steps in the last section "Test and Play" to test out the "fire" remote event.