Skip to content

Instantly share code, notes, and snippets.

@fuzzblob
Created March 4, 2019 16:37
Show Gist options
  • Save fuzzblob/a4990be8ae0e91aa24037f3791768c36 to your computer and use it in GitHub Desktop.
Save fuzzblob/a4990be8ae0e91aa24037f3791768c36 to your computer and use it in GitHub Desktop.
Some methods to use the cameras Viewport to apply panning and distnace attenuation to audio
/*
* ABOUT:
*
* Simple script to convert Vector3 position to 2D panning position and distance
* attenuation based on the camera viewport. useful for 2D and isometric games.
*
* ############################################################
*
* MIT License
*
* Copyright (c) 2019 Maris Tammik
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
using UnityEngine;
public static class FlatPanning {
// The camera we use to measure distances on (should be setup by your audio engine setup)
internal static Camera Cam;
// The config file. this is a proprietary format. setup your own using ScriptableObject?
private static MConfig _config = MManager.Config;
/// <summary>
/// Update each Instance position each frame
/// </summary>
internal static FunctionResult UpdateFlatPosition(Instance target, Vector3 position) {
// ensure camera
if (Cam == null) Cam = Camera.main;
Vector2 viewportPoint = Cam.WorldToViewportPoint(position);
// store results for comparison
float distance = ViewportToDistance(viewportPoint);
float pan = ViewportToPan(viewportPoint.x);
// compare to calulated values
if (target.Parameters.Distance == distance && target.Parameters.Pan == pan)
return FunctionResult.NoActionNeeded;
// change detected! set values on MInstanceParameter
target.Parameters.Distance = distance;
target.Parameters.Pan = pan;
target.Parameters.IsDirty = true;
// request updating associated MVoices
return FunctionResult.UpdateRequested;
}
/// <summary>
/// Convert viewport position to panning value
/// </summary>
public static float ViewportToPan(float viewPosX) {
// turn viewport coordinates to pan value: "0 to 1" into "-1 to 1"
float pan = Mathf.Clamp((viewPosX * 2) - 1, -1, 1);
if (_config.FlatPanningDebth == null)
// no pan depth manipulation
return pan;
// use AnimationCurve to bend values
// (default = AnimationCurve { Keyframe(0,0), Keyframe(1,1)})
if (pan >= 0)
return MManager.Config.FlatPanningDebth.Evaluate(Mathf.Abs(pan));
else
return -1 * MManager.Config.FlatPanningDebth.Evaluate(Mathf.Abs(pan));
}
/// <summary>
/// Compute distance based on inner- and outer-rectangle
/// </summary>
public static float ViewportToDistance(Vector2 viewportPos) {
// converting 0to1 range top -1to1 range
// also requires to scale the rectangles
float innerMagin = _config.FlatInnerMargin * 2;
float outerMagrin = _config.FlatOuterMargin * 2;
// remove center corner offset from position
Vector2 offsetPos = new Vector2(
Mathf.Abs(viewportPos.x * 2 - 1),
Mathf.Abs(viewportPos.y * 2 - 1)) - new Vector2(1 - innerMagin, 1 - innerMagin);
// get the max distance
float maxLength = innerMagin + outerMagrin;
// corner case (literally)
if (offsetPos.x < maxLength
&& offsetPos.y < maxLength) {
maxLength = new Vector2(innerMagin + outerMagrin, innerMagin + outerMagrin).magnitude;
}
// interpolate by how far offsetPos is along maxLength
float x = Mathf.Lerp(0, _config.FlatMaxDistance,
Mathf.Clamp(offsetPos.x / maxLength, 0, 1));
float y = Mathf.Lerp(0, _config.FlatMaxDistance,
Mathf.Clamp(offsetPos.y / maxLength, 0, 1));
// get distance (pythagoras)
return Mathf.Sqrt(x * x + y * y);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment