- Home /
Make camera audio listener with FMODUnity
Hi, I'm a sound designer and cowboy programmer. By cowboy I mean show me how to do something and I can apply it to my own objects / set my own variables etc etc. This is beyond my experience but something tells me it should be possible.
I have been using some scripts created by another similar sound designer/programmer but obviously slightly better than myself!
He has created this script to tell FMOD where the player is relative to a sound emitter by passing it the 3D info about the player. Problem is, it was written for a 1st person game. I am making a platformer. Basically I need this to correspond to the Camera instead as, in a platformer, the camera is the audio listener. The stuff about footsteps etc I will need to keep on the actual player but I'm not so worried about that right now so edit that out (same with the wallpat etc). Could someone edit this script for me to be attached to the camera instead of the player so that FMOD can receive its 3D position info.
Here is some basic FMOD 3D Listener programmers (C++ not C# but should be similar) info:
EventSystem::set3DListenerAttributes This updates the position, velocity and orientation of the specified 3D sound listener.
C++ Syntax
FMOD_RESULT EventSystem::set3DListenerAttributes( int listener, const FMOD_VECTOR pos, const FMOD_VECTOR vel, const FMOD_VECTOR forward, const FMOD_VECTOR up );
C Syntax
FMOD_RESULT FMOD_EventSystem_Set3DListenerAttributes( FMOD_EVENTSYSTEM eventsystem, int listener, const FMOD_VECTOR pos, const FMOD_VECTOR vel, const FMOD_VECTOR forward, const FMOD_VECTOR * up );
Parameters
listener
Listener ID in a multi-listener environment. Specify 0 if there is only 1 listener.
pos
Address of a variable that receives the position of the listener in world space, measured in distance units. You can specify 0 or NULL to not update the position.
vel
Address of a variable that receives the velocity of the listener measured in distance units per second. You can specify 0 or NULL to not update the velocity of the listener.
forward
Address of a variable that receives the forwards orientation of the listener. This vector must be of unit length and perpendicular to the up vector. You can specify 0 or NULL to not update the forwards orientation of the listener.
up
Address of a variable that receives the upwards orientation of the listener. This vector must be of unit length and perpendicular to the forwards vector. You can specify 0 or NULL to not update the upwards orientation of the listener.
and the script in question (FMODPlayer.cs):
Code:
using UnityEngine; using System; using System.Collections; [RequireComponent (typeof (CharacterController))]
public class FMODPlayer : MonoBehaviour { private static FMOD.EventSystem eventsystem = null; private static FMOD.System system = null; private FMOD.VECTOR pos; private FMOD.VECTOR vel; private FMOD.VECTOR forward; private int listener = 0; private FMOD.VECTOR up; private CharacterController me; public string SoundController = "SoundControl"; public float TurnStepThreshold = 80; private FootstepsSound footsteps; private WallPatSound wallsound; private bool wastouchingwall = false; private bool hasYelled = false; private bool isStepping = false; private bool inTrigger = false; private bool wasMoving = true; private float stepDirection; // private Transform activePlatform; private Vector3 activeLocalPlatformPoint; private Vector3 activeGlobalPlatformPoint; private Quaternion activeLocalPlatformRotation; private Quaternion activeGlobalPlatformRotation;
void Start () { me = GetComponent<CharacterController>(); if (!GameObject.Find(SoundController)) { Debug.LogError("FMODsystem for FMODPlayer on "+this.transform.name+" not found!"); Destroy(this); } else{ FMODsystem SoundSystem = GameObject.Find(SoundController).GetComponent<FMODsystem>(); eventsystem = SoundSystem.getEventSystem(); //system = SoundSystem.getSystem(); } footsteps = GetComponent<FootstepsSound>(); wallsound = GetComponent<WallPatSound>();
}
void Update () { // Debug.Log("I am ALIVE"); pos = VectorConvert(this.transform.position); Debug.Log("Playa Position is now " + pos.x + ", " + pos.y + ", "+ pos.z); vel = VectorConvert(me.velocity); // Debug.Log("Viewer speed should be " + me.velocity.magnitude);
forward = VectorConvert(this.transform.forward); up = VectorConvert(this.transform.up); FMOD.RESULT result = eventsystem.set3DListenerAttributes(listener, ref pos, ref vel, ref forward, ref up); // result = system.set3DListenerAttributes(listener, ref pos, ref vel, ref forward, ref up);
ERRCHECK(result); FMOD.VECTOR RealPos = VectorConvert(Vector3.zero); eventsystem.get3DListenerAttributes(listener, ref RealPos, ref vel, ref forward, ref up); //Debug.Log("Viewer velocity is now " + vel.x + ", " + vel.y + ", "+ vel.z); //Debug.Log("Playa Position is now " + RealPos.x + ", " + RealPos.y + ", "+ RealPos.z); //Debug.Log("Player speed is " + Mathf.Sqrt(Mathf.Pow(me.velocity.x,2)+Mathf.Pow(me.velocity.z,2)));
// if (me.collisionFlags == CollisionFlags.Sides) // { // //Debug.Log("Touching sides!"); // if (!wastouchingwall){ // footsteps.setWall(1f); // wastouchingwall = true; // }else // { // footsteps.setWall(me.velocity.magnitude/3); // } // }else{ // footsteps.setWall(0); // wastouchingwall = false; // } footsteps.setSpeed(me.velocity.magnitude); footsteps.setPos(me.transform.position, me.velocity); if(!isStepping) { footsteps.Begin(); } if (me.velocity.magnitude > 2.5 && wastouchingwall) { wastouchingwall = false; hasYelled = false; //Debug.Log("notWAlledanymore"); } if(wastouchingwall == false) { wallsound.setWall(0); }
if(me.velocity.magnitude == 0)
{
if (wasMoving)
{
stepDirection = transform.eulerAngles.y;
wasMoving = false;
}
if(((stepDirection - transform.eulerAngles.y) > TurnStepThreshold) || ((stepDirection - transform.eulerAngles.y) < -TurnStepThreshold))
{
footsteps.End();
footsteps.setSpeed(1f);
footsteps.Begin();
footsteps.setSpeed(0.01f);
//Debug.Log("I just stepped around");
stepDirection = transform.eulerAngles.y;
}
footsteps.setSpeed(0.1f);
}else
{
wasMoving = true;
}
}
private void FixedUpdate() { if (!inTrigger && footsteps != GetComponent<FootstepsSound>()) { footsteps = SwitchSteps(me); } // Moving platform support // if (activePlatform != null) { // Vector3 newGlobalPlatformPoint = activePlatform.TransformPoint(activeLocalPlatformPoint); // Vector3 moveDistance = (newGlobalPlatformPoint - activeGlobalPlatformPoint); // if (moveDistance != Vector3.zero) // { // Debug.Log(moveDistance); // transform.Translate(moveDistance); // } // // // If you want to support moving platform rotation as well: // Quaternion newGlobalPlatformRotation = activePlatform.rotation activeLocalPlatformRotation; // Quaternion rotationDiff = newGlobalPlatformRotation Quaternion.Inverse(activeGlobalPlatformRotation); // // // Prevent rotation of the local up vector // rotationDiff = Quaternion.FromToRotation(rotationDiff transform.up, transform.up) rotationDiff; // // transform.rotation = rotationDiff transform.rotation; // } // // activePlatform = null; // // // // Moving platforms support // if (activePlatform != null) { // activeGlobalPlatformPoint = transform.position; // activeLocalPlatformPoint = activePlatform.InverseTransformPoint (transform.position); // // // If you want to support moving platform rotation as well: // activeGlobalPlatformRotation = transform.rotation; // activeLocalPlatformRotation = Quaternion.Inverse(activePlatform.rotation) transform.rotation; // } }
private void OnControllerColliderHit (ControllerColliderHit hit) {
// Make sure we are really standing on a straight platform
// Not on the underside of one and not falling down from it either!
if (hit.moveDirection.y < -0.9 && hit.normal.y > 0.5) {
//activePlatform = hit.collider.transform;
//Debug.Log("I'm on a platform look at me");
}
Camera mainCamera = FindCamera();
RaycastHit rahit;// = new RaycastHit();
Vector3 Middle = new Vector3(0.5f,0.5f,0f);
Ray ray = mainCamera.ViewportPointToRay(Middle);
if (0.5 < hit.normal.y && hit.normal.magnitude < 1.01)
{
//it's a floor or a roof
return;
}
wallsound = SwitchWall(hit.collider);
if (wallsound == null)
{
return;
}
if (!Physics.Raycast(ray, out rahit, 2) && hasYelled)
{
//Debug.Log("I don't touch a thing");
wallsound.setWall(0);
return;
}
//Debug.Log("Normal + Direction =" + 1/(hit.normal + me.velocity).magnitude);
float newWallvalue = (1/(hit.normal + me.velocity).magnitude);
if (hasYelled || me.velocity.magnitude < 2)
{
//Debug.Log("Was yelling before, reducign number");
newWallvalue *= 0.8f;
}
//Debug.Log(newWallvalue);
//Debug.Log("hit a wall");
if(me.velocity.magnitude < 0.2)
{
newWallvalue = 0;
}
wallsound.setPos(hit.point, Vector3.zero);
wallsound.setWall(newWallvalue);
if (newWallvalue > 0.8)
{
hasYelled = true;
//Debug.Log("I yelled");
}
wastouchingwall = true;
//Debug.Log("Hit Normal = " + hit.normal.ToString());
}
private void OnTriggerEnter(Collider other) { if (other.GetComponent<FootstepsSound>() != null) { //Debug.Log("The thing has a footsteps connected"); footsteps = SwitchSteps(other); } } private void OnTriggerStay(Collider other) { inTrigger = true; if (other.GetComponent<FootstepsSound>() != null) { if (footsteps != other.GetComponent<FootstepsSound>()) { //Debug.Log("The thing has a footsteps connected"); footsteps = SwitchSteps(other); } } } private void OnTriggerExit(Collider other) { inTrigger = false; }
private FootstepsSound SwitchSteps(Collider hitthing) { FootstepsSound newfootsteps; newfootsteps = hitthing.GetComponent<FootstepsSound>(); float curspeed = footsteps.getSpeed(); footsteps.End(); footsteps.setSpeed(0); newfootsteps.setSpeed(curspeed);
newfootsteps.Begin(); return newfootsteps; }
private WallPatSound SwitchWall(Collider hitthing) { WallPatSound newWall = null; if(hitthing.GetComponent<WallPatSound>() != null) { newWall = hitthing.GetComponent<WallPatSound>(); } else if(GetComponent<WallPatSound>() != null) { newWall = GetComponent<WallPatSound>(); } if (newWall == null) { Debug.LogWarning("There is no wall-pat sound available here"); return newWall; } if (newWall != wallsound) { Debug.Log("Changing Wallpat Sound"); float curwall = wallsound.getWall(); wallsound.setWall(0); wallsound.End(); newWall.setWall(curwall); newWall.Begin(); } return newWall; }
private static void checkTurning(float oldRotation) {
}
private static void ERRCHECK(FMOD.RESULT result) { if (result != FMOD.RESULT.OK) { Debug.Log("FMOD error! " + result + " - " + FMOD.Error.String(result)); } }
private FMOD.VECTOR VectorConvert (Vector3 Vector) { FMOD.VECTOR end; end.x = Vector.x; end.y = Vector.y; end.z = Vector.z; return end; }
private Camera FindCamera ()
{ if (camera) { return camera; } else { return Camera.main; } } }
Thanks!!! (and sorry about the really really long post / script with lots commented out... :S)
You posted a block of code which isn't yours, and you're asking us to make it work for you. If you're not going to try to understand what you are doing, then you should $$anonymous$$m up with a programmer who can do this stuff for you.
You misunderstood his post. He's trying to create 3D audio when Unity already does that, and he didn't ask for someone to write his code, he asked to be shown basic program$$anonymous$$g concepts (and what he was doing wrong), so that he could attempt to fix them himself, which is a lot more than can be said for some users who post here. -- Please read the question and understand what the poster is asking before jumping to conclusions. :)
Answer by qJake · Jun 28, 2010 at 12:04 AM
You're reinventing the wheel. Unity already does exactly what you're trying to do, and it does it all for you.
Please read this page very carefully:
http://unity3d.com/support/documentation/Manual/Sound.html
Unity already contains an Audio Listener component that is typically attached to a camera (but it doesn't have to be, necessarily), and "receives" audio from the surrounding game world in 3D, applying rolloff factors, volume, and other effects. Unity 3 will also come with additional effects like reverb, echo, filtering, and custom rolloff curves.
There is absolutely no need for you to tap into the FMOD subsystem in order to achieve what you want, and these scripts are probably mostly useless to you.
Except that I'm a student and Unity 3 isn't out yet. Unity 2.6's Audio engine is so simple and useless it hurts! Thus, I'm using the F$$anonymous$$OD designer. Also, what are these "effects" you talk about? Unity 2.61 doesn't have any! No reverb, no filters and the rolloff is really not very good. Plus it just has audio clips playing. No interactive sounds. I don't know if you are aware but game sound has come a lot further than the abilities of Unity 2.61. Do you even know what F$$anonymous$$OD does?!?
Yes, I know exactly what Fmod does. If you want "interactive sounds", you need to script that capability into your game. You can control playback, speed, pitch, etc. And like I said, effects like reverb, echo, filtering, and rolloff curves are co$$anonymous$$g to Unity 3, which comes out this summer (read: very soon). So if you really need effects, you'll just have to wait until Unity 3, because it's really not worth it to try and write a plugin for something that's going to be released in the near future. You should check the Unity blog; they've released a video detailing the new audio features.