Last active
March 6, 2024 17:43
-
-
Save bamacken/5cfdac3a2e025918c05a to your computer and use it in GitHub Desktop.
Unity - Weighted 2D Camera movement based on the influence of "interest points".
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//usage: Set Camera to Orthographic and use CameraInfluence.AddInfluence(gameObject,influence); | |
//permanent interest points such as onscreen players should have influence set to 0.5f | |
using UnityEngine; | |
using System.Collections; | |
using System.Collections.Generic; | |
using Unity.VisualScripting; | |
public class CameraInfluence : MonoBehaviour | |
{ | |
/*public static*/ | |
public float min, max = 0.0f; | |
public Vector3 CameraTarget; | |
public Vector3 InfluenceTarget; | |
public float InterpolationSpeed = 0.001f; | |
public float distance = 75f; | |
/*public*/ | |
public static Dictionary<GameObject, float> InfluenceObjects; | |
public static int InfluencePoints = 0; | |
/*private*/ | |
private RaycastHit hit; | |
private Camera cam; | |
private float[] VariedInfluence; | |
private static CameraInfluence _instance; | |
private static readonly object padlock = new object(); | |
/// <summary> | |
/// Threadsafe singleton instance | |
/// </summary> | |
public static CameraInfluence Instance | |
{ | |
get | |
{ | |
lock (padlock) | |
{ | |
if (_instance == null) | |
{ | |
_instance = FindObjectOfType<CameraInfluence>(); | |
} | |
return _instance; | |
} | |
} | |
} | |
// Use this for initialization | |
void Awake() | |
{ | |
cam = GetComponent<Camera>(); | |
InfluenceObjects = new Dictionary<GameObject, float>(); | |
InfluenceTarget = Vector3.zero; | |
VariedInfluence = new float[] { 1.0f, 2.0f, 2.5f, 3.0f, 3.5f, 4.0f, 4.5f }; | |
} | |
// Update is called once per frame | |
void FixedUpdate() | |
{ | |
if (InfluenceObjects.Count > 0) | |
{ | |
float previousDistance = 0f; | |
float totalDistance = 0f; | |
Vector3 previous = Vector3.zero; | |
foreach (KeyValuePair<GameObject, float> pair in InfluenceObjects) | |
{ | |
if (previous == Vector3.zero) | |
{ | |
previous = pair.Key.transform.position; | |
} | |
float dist = Vector3.Distance(previous, pair.Key.transform.position); | |
if (dist > previousDistance) | |
{ | |
previousDistance = dist; | |
} | |
} | |
totalDistance = previousDistance; | |
if (totalDistance > 50) | |
{ | |
distance = totalDistance / InfluenceObjects.Count; | |
} | |
if (InfluenceObjects.Count == 1) | |
{ | |
CameraTarget = Vector3.Lerp(CameraTarget, midpointplus(InfluenceObjects), Time.time * InterpolationSpeed); | |
transform.position = new Vector3(CameraTarget.x, CameraTarget.y, -3.0f); | |
cam.orthographicSize = distance; | |
} | |
else | |
{ | |
//need to interpolate further to avoid camera bounce when new influence point is added | |
CameraTarget = Vector3.Lerp(CameraTarget, midpointplus(InfluenceObjects), Time.time * InterpolationSpeed); | |
transform.position = new Vector3(CameraTarget.x, CameraTarget.y, 0); | |
cam.orthographicSize = distance; | |
} | |
} | |
} | |
void OnDrawGizmos() | |
{ | |
Gizmos.color = Color.yellow; | |
Gizmos.DrawWireCube(CameraTarget, new Vector3(1, 1, 1)); | |
Gizmos.color = Color.red; | |
Gizmos.DrawWireCube(CameraTarget, new Vector3(28.5f, 16f, 1f)); | |
} | |
/// <summary> | |
/// Midpoint of multiple vectors. | |
/// </summary> | |
private Vector3 midpointplus(Dictionary<GameObject, float> a) | |
{ | |
if (a.Count > 0) | |
{ | |
//get the vector positions of the all interest points and add the influence | |
foreach (KeyValuePair<GameObject, float> pair in InfluenceObjects) | |
{ | |
if (a.Count == 1) | |
{ | |
InfluenceTarget.x = (pair.Key.transform.position.x); | |
InfluenceTarget.y = (pair.Key.transform.position.y); | |
} | |
else | |
{ | |
InfluenceTarget.x += (pair.Key.transform.position.x * pair.Value); | |
InfluenceTarget.y += (pair.Key.transform.position.y * pair.Value); | |
} | |
} | |
InfluenceTarget.x /= VariedInfluence[a.Count - 1]; | |
InfluenceTarget.y /= VariedInfluence[a.Count - 1]; | |
} | |
return InfluenceTarget; | |
} | |
/// <summary> | |
/// Updates object influence, or adds object and influence | |
/// Checks if influence is 0 and should be removed. | |
/// </summary> | |
/// <param name="obj">Object.</param> | |
/// <param name="influence">Influence.</param> | |
public static void AddInfluence(GameObject obj) | |
{ | |
float influence = 0.5f; | |
if (influence > 0) | |
{ | |
if (InfluenceObjects.ContainsKey(obj)) | |
InfluenceObjects[obj] = influence; | |
else | |
InfluenceObjects.Add(obj, influence); | |
} | |
else | |
if (InfluenceObjects.ContainsKey(obj)) | |
InfluenceObjects.Remove(obj); | |
} | |
public static void AddInfluence(GameObject obj, float influence) | |
{ | |
if (influence > 0) | |
{ | |
if (InfluenceObjects.ContainsKey(obj)) | |
InfluenceObjects[obj] = influence; | |
else | |
InfluenceObjects.Add(obj, influence); | |
} | |
else | |
{ | |
if (InfluenceObjects.ContainsKey(obj)) | |
InfluenceObjects.Remove(obj); | |
} | |
} | |
public static void RemoveInfluence(GameObject obj) | |
{ | |
if (InfluenceObjects.ContainsKey(obj)) | |
InfluenceObjects.Remove(obj); | |
} | |
void OnDisable() | |
{ | |
//InfluenceObjects = null; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment