Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by Algia · Mar 25, 2015 at 06:05 PM · audiophotongun

How can I locally play audio over a network without rapid RPC calls?

I'm currently working on a FPS game. I had audio working quite well on single player for my rifle (fires about every .1 second), but then I started using RPC calls for other players to hear the audio as well. This caused a terrible stutter in the audio, and reduced the quality greatly. Is there a way I could have the players locally determine the shots and play them at the shooting player's point? I want to try to avoid calling excessive amounts of RPCs, to avoid the bandwidth and lag issues.

My code Currently:

GetComponent().RPC("Fire", PhotonTargets.Others, gunAudioClip, transform.position); //(called every .1 seconds)

 [RPC]
 public void Fire(int gunAudio, Vector3 position)
 {

     AudioSource.PlayClipAtPoint(AudioClips[gunAudio], position);
 }

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
2
Best Answer

Answer by PouletFrit · Mar 25, 2015 at 10:49 PM

If you want players to receive "input" information (when they are firing) from other players, you won't have choice but to inform them, which mean RPC in this case.

First, since you are calling the same Audioclip on the same AudioSource to play the sound so often, it doesn't have time to finish playing it, that you're calling again to play it, so it just keep restarting it without fully playing it (except the last time it get called of course). You need to have one AudioSource for every sound you wish to play simultaneously.

But creating tons of AudioSource isn't really performance and memory efficient, also you would need to destroy them once you dont need them anymore, so I strongly advise you to use a pooling system for this. There is great plugins in the Unity Asset Store that can do it for you, or if you wish to implement your own pooling here is an exemple:

 public class AudioPoolManager : MonoBehaviour {
 
     // The amount of AudioSource we will initialize the pool with
     public int poolSize = 10;
 
     // We use a queue since it will remove the instance at the same time that we are asking for one
     private Queue<AudioSource> pool;
 
     void Awake()
     {
         pool = new List<AudioSource>();
 
         // Here we create initialize our pool with the specified amount of instance,
         for (int i = 0; i < poolSize; i++) 
         {
             pool.Add(CreateNewInstance());
         }
     }
 
     private AudioSource CreateNewInstance() 
     {
         GameObject go = new GameObject("AudioSourceInstance");
         // Let's group in our instance under the pool manager
         go.transform.parent = this.transform;
         AudioSource as = go.AddComponent<AudioSource>();
 
         return as;
     }
 
     // When we are asking for an AudioSource, we will first check if we still have one in our
     // pool, if not create a new instance
     public AudioSource GetAudioSource()
     {
         if (pool.Count < 1) {
             return CreateNewInstance();
         } else {
             return pool.Dequeue();
         }
     }
 
     // Always return the AudioSource instance once you are done with it
     public void ReturnAudioSource(AudioSource instance) 
     {
         pool.Add(instance);
     }
 }

So here is how you would use it:

 // Keep a reference somewhere
 public AudioPoolManager audioPool;
 
 [RPC]
 public void Fire(Vector3 position)
 {
     AudioSource as = audioPool.GetAudioSource();
     as.PlayClipAtPoint(gunAudio, position);
 
     // We need to know when the audio clip has finished playing
     // So we can return the audio source instance to the pool manager
     StartCoroutine(WaitForAudioClipToFinish(as, gunAudio.length));
 }
 
 private Enumerator WaitForAudioClipToFinish(AudioSource as, float audioClipDuration)
 {
     yield return new WaitForSeconds(audioClipDuration);
     audioPool.ReturnAudioSource(as);
 } 

Also, you shouldn't send the Audioclip with your RPC. If you have only one sounds that can be played, there is no need to send it, just keep a reference on the other player object and play that sound with that reference. If you wish to play multiple sound use an byte enum to identify which sound to play.

 public Audioclip rifleAudio;
 public Audioclip shotgunAudio;
 
 public enum PlayerSound : byte
 {
     rifleSound,
     shotgunSound
     // etc...
 }
 
 public void Fire()
 {
     GetComponent().RPC("Fire", PhotonTargets.Others, (byte)PlayerSound.rifleSound, transform.position);
 }
 
 [RPC]
 public void Fire(byte playerSoundByte, Vector3 position)
 {
     PlayerSound soundType = (PlayerSound)playerSoundByte;
 
     if (soundType == PlayerSound.rifleSound) {
         AudioSource.PlayClipAtPoint(rifleAudio, position);
     } else if (soundType == PlayerSound.shotgunSound) {
         AudioSource.PlayClipAtPoint(shotgunAudio, position);
     }
 }

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Algia · Mar 25, 2015 at 11:13 PM 0
Share

Okay so that is my mistake, I changed out that variable for the out of context variables, and it changed the code entirely...

I changed my code to test the same system WITHOUT RPC's, and it actually did the exact same issue.

Is it possible that switching to OneShotAudio from a designated AudioSource be the cause of my problem? Can the OneShotAudio delete the audio too early or something? It basically causes a high pitched beep on a fairly random interval

avatar image PouletFrit · Mar 26, 2015 at 02:41 PM 0
Share

Ah ok! I think I get what is your problem.

I'll update my answer...

avatar image
1

Answer by Addyarb · Mar 25, 2015 at 08:55 PM

Assuming you're creating an authoritative server, you should just have the server instantiate the object with an audio clip. So just add if(Network.isServer) whenever you call your RPC. Alternatively, you can make a script that just holds all possible audio clips and attach it to the players individually. Then, when you want that sound to play, just call an RPC function with a for each loop.

Something like:

 GameObject[] players = GameObject.FindGameObjectsWithTag("Player");
 foreach (GameObject player in players){
 AudioScript audioScript = player.GetComponent<AudioScript>();
 audioScript.PlaySound(audioScript.sound1);
 }

Then Audio Script would look like so:

 public AudioSource source;
 public AudioClip sound1;
 
 public void PlaySound(Audioclip sound){
 source.PlayOneShot(sound);
 }

}

Good luck!

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

3 People are following this question.

avatar image avatar image avatar image

Related Questions

Help with Gui texture/Audio 1 Answer

How do I add sound to this script 1 Answer

How to make a pick up gun script? 0 Answers

Gun Sound On Mousedown 2 Answers

how to keep 1 audio listener 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges