Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

ClientRpc call not going through to host?

Discussion in 'Multiplayer' started by Palimon, Jul 14, 2015.

  1. Palimon

    Palimon

    Joined:
    Apr 18, 2013
    Posts:
    225
    Hey, working through my first implementation of multiplayer. I can't seem to get audio sources to play. When the playing uses a gun, I use a command to fire a bullet and create a PlayOneShot audio source on the server. I see the bullets, but I don't hear the audio. What am I missing? Do I need to somehow sync the audio source to each client manually?
     
  2. Bmandk

    Bmandk

    Joined:
    Aug 18, 2012
    Posts:
    70
    I think the best implementation of sound would be to send the client an Rpc call and in the function play the sound.
     
  3. Palimon

    Palimon

    Joined:
    Apr 18, 2013
    Posts:
    225
    Hmm, is there an easy way to deal with distance for volume that way?
     
  4. Bmandk

    Bmandk

    Joined:
    Aug 18, 2012
    Posts:
    70
    Well, I'm guessing it's the player that shoots a bullet, and each client has the camera following their own player. Then you can just attach an audiosource on each player and play it whenever that player is shooting. Then have the audiolistener only on the clients player. Be sure to enable 3D sounds which will automatically handle distance with audiosources and listeners.
     
  5. Palimon

    Palimon

    Joined:
    Apr 18, 2013
    Posts:
    225
    Well, I can certainly give that a shot. Know of any reason why it wouldn't be playing from the server though? I'll need to have this option for explosions of targets and other sound effects.
     
    Last edited: Jul 15, 2015
  6. Bmandk

    Bmandk

    Joined:
    Aug 18, 2012
    Posts:
    70
    Are you using the Commands and RpcClient attributes?

    Here's the rundown:

    Receive input to shoot.
    Run a [Command] function.
    In the [Command] function, instantiate and spawn the bullet object. Also call a [RpcClient] function that will play the audio on the players AudioSource.

    Code (CSharp):
    1. public AudioClip fireBulletSound;
    2.  
    3. [Command]
    4. public void Cmd_SpawnBullet()
    5. {
    6.     GameObject bullet = Instantiate(bulletPrefab, player.transform.position, player.transform.rotation);
    7.     NetworkServer.Spawn(bullet);
    8.     Rpc_PlaySound(fireBulletSound);
    9. }
    10.  
    11. [RpcClient]
    12. public void Rpc_PlaySound(AudioClip sound)
    13. {
    14.     AudioSource audioSource = GetComponent<AudioSource>();
    15.     audioSource.PlayOneShot(sound, 1f);
    16. }
    Note that I just wrote this here, not tested. But it should work fine, looking away from syntax errors.
     
  7. Palimon

    Palimon

    Joined:
    Apr 18, 2013
    Posts:
    225
    Ok, I'll give that a shot - I haven't used any RPCs yet. For an asteroid explosion, I would have a similar Rpc call method on the asteroid that is called by the server when it determines the asteroid needs to explodes, and the Rpc would play audio using an audio source on the asteroid, and this would happen on the client? From http://docs.unity3d.com/Manual/UNetActions.html it sounds like all objects can have Rpc methods.
     
  8. Bmandk

    Bmandk

    Joined:
    Aug 18, 2012
    Posts:
    70
    Yeah, all objects that are NetworkBehaviours if I remember correctly. But that's exactly what you'd need to do.
     
  9. Palimon

    Palimon

    Joined:
    Apr 18, 2013
    Posts:
    225
    Ok, here's what I have:

    Code (CSharp):
    1. public override void Operate(List<KeyCode> allKeys, List<KeyCode> allKeyDowns, List<KeyCode> allKeyUps)
    2.     {
    3.         if (allKeys.Contains(KeyCode.Space))
    4.         {
    5.             if (cooldown <= 0)
    6.             {
    7.                 if (Input.GetKey("space"))
    8.                 {
    9.                     // Reset gun cooldown.
    10.                     cooldown = 1;
    11.  
    12.                     Rpc_ShotSound();
    13.                 }
    14.             }
    15.  
    16.             // Create a bullet
    17.             Vector3 bulletStartPosition = new Vector3(this.transform.position.x, this.transform.position.y, this.transform.position.z + 2);
    18.             GameObject bulletClone = Instantiate(Gun.BulletPrefab, bulletStartPosition, transform.rotation) as GameObject;
    19.  
    20.             // Accellerate the bullet
    21.             Vector3 newVector = this.transform.forward * Gun.BULLET_SPEED + this.transform.parent.transform.parent.transform.GetComponent<Rigidbody>().velocity;
    22.             bulletClone.GetComponent<Rigidbody>().AddForce(newVector, ForceMode.VelocityChange);
    23.  
    24.             // Spawn the bullet
    25.             Destroy(bulletClone, 2f);
    26.             NetworkServer.Spawn(bulletClone);
    27.         }
    28.     }
    29.  
    30.     [ClientRpc]
    31.     public void Rpc_ShotSound()
    32.     {
    33.         // Create firing sound.
    34.         float vol = Random.Range(volLowRange, volHighRange);
    35.         aSource.PlayOneShot(aClipShoot, vol);
    36.     }
    Operate() is called by a Cmd method inside the player script. I hit a breakpoint at Rpc_ShotSound(); so I can see I'm getting there. I never reach a breakpoint inside Rpc_ShotSound() though.
     
  10. Bmandk

    Bmandk

    Joined:
    Aug 18, 2012
    Posts:
    70
    Hmm, that seems a bit weird. I just installed UnityVS myself, so I don't know much about the breakpoints. But it might be interfering with networking? Try maybe using Debug.Log instead, as it won't stop the code. I would just guess that pausing the game with networking kinda messes up the timing.

    Also a bit unrelated, but if I understand this correctly, this code will only run on the host, since you're checking if the user has pressed a key, but Operate is only run on the host. That might not want to be your intention.
     
  11. Palimon

    Palimon

    Joined:
    Apr 18, 2013
    Posts:
    225
    I had the same behaviour with/without the breakpoints.

    Actually, I'm capturing all the various inputs at the player and passing them through to the server via a Cmd :). Operate is called by a Cmd on the player. Since my player can control various vehicles, I needed to move most of the control complexity to the server.
     
  12. Bmandk

    Bmandk

    Joined:
    Aug 18, 2012
    Posts:
    70
    Well, if the input works, no problem.

    As for the actual problem, the only reason I could see it not executing the Rpc function would be if you're not calling it from the host. But since you're only calling Operate() from a Cmd, I don't see how it would be possible. Just to be sure, try putting the breakpoint in an if (isServer) state once you've reached the point where you want to run the Rpc function? It should go to the breakpoint, but I'm running out of ideas.
     
  13. Palimon

    Palimon

    Joined:
    Apr 18, 2013
    Posts:
    225
    Based on a few comments in (http://forum.unity3d.com/threads/unet-clientrpc-not-executing-on-host.320288/) I'm wondering if how I'm setting up this script is a problem. The Gun gameobject and script are around at launch, but I spawn the controller later. Also, my Operate() method in GunController is called inside my player script's Cmd and passed all the inputs. isServer is true when I come through Operate. Details below.

    Here's the game objects inside the scene before I start the game (so they're there at game launch, and I assume I don't need to worry about doing a NetworkServer.Spawn):
    Guns.PNG Gun Spec.PNG
    And here's my Gun script and GunController scripts:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.Networking;
    4. using System.Collections.Generic;
    5.  
    6. public class Gun : Equipment
    7. {
    8.     public GameObject BulletPrefab;
    9.     public float RateOfFirePerSecond = 2f;
    10.     public const int BULLET_SPEED = 15;
    11.  
    12.     // Use this for setting up references
    13.     public void Awake()
    14.     {
    15.         // Add Controller
    16.         Controller = gameObject.AddComponent<GunController>();
    17.     }
    18. }
    19.  
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.Networking;
    4. using System.Collections.Generic;
    5.  
    6. public class GunController : EquipmentController
    7. {
    8.     private float cooldown = 0;
    9.     private Gun Gun;
    10.  
    11.     public AudioClip aClipShoot;
    12.     private AudioSource aSource;
    13.     private float volLowRange = .75f;
    14.     private float volHighRange = 1.25f;
    15.  
    16.  
    17.     void Start()
    18.     {
    19.         aSource = GetComponent<AudioSource>();
    20.         this.Gun = this.gameObject.GetComponent<Gun>();
    21.     }
    22.  
    23.     // TODO: Make sure this only runs on the server.
    24.     [Server]
    25.     void Update()
    26.     {
    27.         if (cooldown > 0)
    28.         {
    29.             cooldown -= this.Gun.RateOfFirePerSecond * Time.deltaTime;
    30.         }
    31.     }
    32.  
    33.     public override void Operate(List<KeyCode> allKeys, List<KeyCode> allKeyDowns, List<KeyCode> allKeyUps)
    34.     {
    35.         if (allKeys.Contains(KeyCode.Space))
    36.         {
    37.             if (cooldown <= 0)
    38.             {
    39.                 if (Input.GetKey("space"))
    40.                 {
    41.                     // Reset gun cooldown.
    42.                     cooldown = 1;
    43.  
    44.                     if (isServer)
    45.                     {
    46.                         Debug.LogWarning("IsServer");
    47.                     }
    48.  
    49.                     Rpc_ShotSound();
    50.                 }
    51.             }
    52.  
    53.             // Create a bullet
    54.             Vector3 bulletStartPosition = new Vector3(this.transform.position.x, this.transform.position.y, this.transform.position.z + 2);
    55.             GameObject bulletClone = Instantiate(Gun.BulletPrefab, bulletStartPosition, transform.rotation) as GameObject;
    56.  
    57.             // Accellerate the bullet
    58.             Vector3 newVector = this.transform.forward * Gun.BULLET_SPEED + this.transform.parent.transform.parent.transform.GetComponent<Rigidbody>().velocity;
    59.             bulletClone.GetComponent<Rigidbody>().AddForce(newVector, ForceMode.VelocityChange);
    60.  
    61.             // Spawn the bullet
    62.             Destroy(bulletClone, 2f);
    63.             NetworkServer.Spawn(bulletClone);
    64.         }
    65.     }
    66.  
    67.     [ClientRpc]
    68.     void Rpc_ShotSound()
    69.     {
    70.         Debug.LogWarning("RPC return");
    71.  
    72.         // Create firing sound.
    73.         float vol = Random.Range(volLowRange, volHighRange);
    74.         aSource.PlayOneShot(aClipShoot, vol);
    75.     }
    76. }
    77.  
     
  14. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
    is GunController a NetworkBehaviour?
     
  15. Palimon

    Palimon

    Joined:
    Apr 18, 2013
    Posts:
    225
  16. peterept2

    peterept2

    Joined:
    Aug 1, 2012
    Posts:
    41
    Hey, I think you are overthinking the bullet part.

    Just add an audio source to your bullet prefab and set it to play your sound on start up.

    When the bullet is spawned on the clients (remote and local) it will play the sound.