New developer here, looking to do some raycasting and controlling audio positioning in 3D space based on the raycasts interactions with other objects. I've got the raycast 'casting' and able to report back where it collides other objects and managed to get audio to play back at that raycast point using AudioSource.PlayClipAtPoint()

However, PlayClipAtPoint doesn't allow me to change the audio 3d attenuation settings as a one shot audio object is generated and then removed immediately and I can't find any parameters to control this new object apart from a volume 0-1 float value.

I came across this post by Aldonaletto:

function PlayClipAt(clip: AudioClip, pos: Vector3): AudioSource; {
   var tempGO = GameObject("TempAudio"); // create the temp object
   tempGO.transform.position = pos; // set its position
   var aSource = tempGO.AddComponent(AudioSource); // add an audio source
   aSource.clip = clip; // define the clip
   // set other aSource properties here, if desired
   aSource.Play(); // start the sound
   Destroy(tempGO, clip.length); // destroy object after clip duration
   return aSource; // return the AudioSource reference

But can't seem to get the local function to work in Unity as it complains about not using C# version 7 or above. If I upgrade the C# version in visual studio I get compiler errors on Unity's side.

Little bit stuck, would appreciate some advice! Some code below, just not sure what to put into the result of the if statement to get this to work.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class raycasting : MonoBehaviour
    public float raycastlength = 3;
    public AudioClip playthis;
    public float ER_Volume = 1F;

    // Use this for initialization
    void Start()
        //Debug.Log("I'm a sphere, yo!");

    // Update is called once per frame
    void Update()
        RaycastHit hit;
        Ray forwardray = new Ray(transform.position, Vector3.forward);

        //draw the raycast in scene view
        Debug.DrawRay(transform.position, Vector3.forward * raycastlength, Color.white);

        if (Input.GetMouseButtonDown(0))
            //Debug.Log("We pressed the fire button!");
            if (Physics.Raycast(forwardray, out hit, raycastlength))
                if (hit.collider.tag == "evil")
                    Debug.Log("Raycast Hit!");
                    Debug.Log("Distance to object:" + hit.distance);
                    //Debug.Log("Object hit point:" + hit.point);

                    //play a sound using playclipatpoint, but this doesn't allow us to change attenuation settings
                    AudioSource.PlayClipAtPoint(playthis, hit.point, ER_Volume);
  • \$\begingroup\$ The example you're looking at is coded in UnityScript, a deprecated JavaScript-like language. If you've pasted it directly, that might be the source of your error - you'll need to translate it to Unity C# syntax. This should be a reasonably straightforward adjustment for which there are many existing guides, but feel free to post a question here if you need help with a particular part of the translation. \$\endgroup\$ – DMGregory Mar 12 '19 at 16:08

Thanks to DMGregory for putting me on to the Unity converter tool. The tool Unity have created seemed to struggle to convert the script for some reason. Instead, I tasked myself with breaking it down and re-creating the function in c~ by hand, and think I figured it out. For the people googling this in the future, I managed to get it to work with an empty prefab called 'playclipat' that has an AudioSource attached to it. The Vector3 in the Instantiate command is "hit.point" as that's part of the raycast. The newly cloned 'playclipat' object is then destroyed after the audio clip has finished.

GameObject playclipatclone = Instantiate(playclipat, hit.point, Quaternion.identity);
AudioSource clonecliplength = GetComponent<AudioSource>();
|improve this answer|||||
  • \$\begingroup\$ Well done. :) For improved performance, you might want to consider 1) using a member variable of type AudioSource, so you can get a reference to the component directly from the Instantiate method without a separate GetComponent() search, and 2) using object pooling, to recycle a collection of these prefabs instead of repeatedly constructing & destroying them. \$\endgroup\$ – DMGregory Mar 12 '19 at 23:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.