• 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
0
Question by pankocrust · May 30, 2018 at 02:20 AM · arrayreference

Another Question on Accessing Scripts from a Separate Object

Hi all -

I apologize for posting a new question on this subject, because I can see very clearly that it is a much-discussed issue on the forum. The decentralized nature of scripting makes it a little hard to follow these answers, though. @Unified2000 suggested I start a thread to clarify this point, also.

Here's the deal: I want to load an array of about 100 sound effects that are accessed randomly by instantiated prefabs. With the generous help of this forum, I managed to do this - but only by loading the samples in the prefab code. This slowed things down considerably, since each one of 100 objects was separately loading the sound effects library. (More on that can be seen here: https://answers.unity.com/questions/1511796/instantiating-multiple-sounds-attached-to-multiple.html?childToView=1512076#answer-1512076)

Now, I'm a little lost. My first move was to create a new GameObject called "cliparray" and write a script for the Start function that did the array loading, essentially just this:

 public Object[] clips;
 void Start()
 {
     clips = Resources.LoadAll("Heat", typeof(AudioClip));
 }


This should theoretically load all of the soundfiles from the "Heat" folder. I'm not sure when and where, though. Does this object need to be imported into the game? Is there a way to access this array from my separate Prefab script? I am still a bit confused about the naming conventions in GetComponent(s), but I'm assuming the answer is somewhere in that region. Thanks for the help, everyone.

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
1
Best Answer

Answer by Hellium · May 30, 2018 at 08:56 AM

Instead of a Singleton which produces crappy code, I would go for a ScriptableObject acting like a database. It has multiple advantages:

  1. It is an asset, not a component you attach to a GameObject → You can easily use it accross your scenes without wondering

  2. You don't have to call the Resources.Load which is a function that is not recommended by Unity itself → No loading time at startup, prevent the increase of the startup time and the length of builds


 [CreateAssetMenu()]
 public class AudioClipsDatabase : ScriptableObject
 {
      [SerializeField]
      private AudioClip[] clips;
 
      public AudioClip GetByName( string name )
      {
          for( int i = 0 ; i < clips.Length ; ++i )
              if( string.Equals( name, clips[i].name ) return clips[i] ;
         return null ;
      } 
 
      public AudioClip GetRandomClip()
      {
          return ( clips.Length > 0 ) ? return clips[Random.Range(0, clips.Length)] : null ;
      }    
 }

Once you have created the AudioClipsDatabase.cs file, click on the Create button of the Project tab and then AudioClipsDatabase. You will have an asset in which you can drag & drop all your AudioClips (you had previously put in a folder outside any Resources folder).

Then, in your components, when you need to access one of the AudioClips managed by your database, just do this :

 [SerializeField]
 private AudioClipsDatabase audioClipsDatabase ; // Drag & drop the database ScriptableObject created in your assets

 [SerializeField]
 private AudioSource audioSource; // Drag & drop the audio source component

 public void SwitchAudioClip()
 {
     audioSource.clip = audioClipsDatabase.GetRandomClip() ;
     audioSource.Play() ;
 }


Comment
Add comment · Show 1 · 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 Hellium · May 30, 2018 at 09:14 AM 0
Share

Note : If you have a lot of AudioClips to drag & drop, here is a little tip.

  1. Select the AudioClipsDatabase asset.

  2. Click on the little lock in the top-right corner of the inspector

  3. Select all your AudioClips in your Project tab (using CTRL + left click or SHIFT + left click)

  4. Drag & drop the list into the clips field of the AudioClipsDatabase asset

  5. Unlock the inspector

avatar image
0

Answer by ShadyProductions · May 30, 2018 at 07:21 AM

The easiest solution would be to make a class with a static instance to it so you can access it in all your scripts without even needing to put it inside your scene. This is called a singleton.

 public class SoundLibrary
 {
     // Singleton setup for non monobehaviour
     private static SoundLibrary _instance;
     public static SoundLibrary Instance
     {
         get { return _instance ?? (_instance = new SoundLibrary()); }
     }
 
     private Object[] clips;
     public Object[] GetSounds()
     {
         if (clips != null) return clips;
         clips = Resources.LoadAll("Heat", typeof(AudioClip));
         return clips;
     }
 }

Now you can use it any of your scripts following: SoundLibrary.Instance.GetSounds(); and it will return your clips; once called it will keep the sounds in cache so it doesn't need to get them again each call.


Note: that a singleton is setup differently based on if your class is derived from monobehaviour or not.

This is the monobehaviour singleton way of setting it up:

 private static SomeClass _instance;
 public static SomeClass Instance { get { return _instance; } }

 private void Awake()
 {
     if (_instance != null && _instance != this)
     {
         Destroy(this.gameObject);
     }
     else 
     {
         _instance = this;
     }
 }
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 pankocrust · May 30, 2018 at 08:57 AM 0
Share

Thank you for the help. The first script works great, right out of the gate. I just wanted to ask about the monobehaviour singleton: If I'm using a monobehavior script attached to a prefab - I should use the second code in some manner?

Essentially, this is the script I'm using on the prefab (implementing the first example)..and it works, but I'm curious if I'm missing something:
using System.Collections; using System.Collections.Generic; using UnityEngine;

 public class deleter : $$anonymous$$onoBehaviour
 {
     public GameObject prefab;
     private AudioSource audioSource;
     public Object[] clips;
     private AudioClip playedclip;
     int index;
 
     void Start()
     {
         clips = SoundLibrary.Instance.GetSounds();
         audioSource = gameObject.GetComponent<AudioSource>();
         audioSource.pitch = Random.Range(0.9f, 1.25f);
         index = Random.Range(0, 100);
         playedclip = ((AudioClip)clips[index]);
         audioSource.clip = playedclip;
         audioSource.Play();
 
     }
 
 
 }
avatar image ShadyProductions pankocrust · May 30, 2018 at 10:44 AM 0
Share

The second code is only if you want a singleton usage in a monobehaviour, say you have a class Game$$anonymous$$anager : $$anonymous$$onoBehaviour, You put it on an empty gameobject in your scene, and there should and can only be one of these scripts in your scene, then you can use this monobehaviour singleton, to be able to access this singleton from other monobehaviours without having to get GameObject.Find(blabla).GetComponent<yourscript>(); but directly through the className.Instance

However, it's not always recommended to use singletons unless you specifically have to.

The example you gave looks fine.

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.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

100 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Why does my null reference become instantiated? 1 Answer

Null Reference Exception After refering to an Array 1 Answer

Array values not being initialised unless the object with the (Player) script is selected in the inspector whilst the game is on 1 Answer

Reading reference variable alters said reference variable 1 Answer

How assign gameobjects to a string and reference them again? 3 Answers


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