Decided to start doing devlogs for those interested in keeping up with the project
To ensure they remain at least somewhat useful, they’ll be paired with tutorials. In this case, the camera which took a over a day of messing around and figuring stuff out (I know, I’m slow) but ended in a state that I’m quite happy with.
As per usual, the full script (Creative Commons 4.0) can be found below.
Devlog
Code
To save time I just annotated the code heavily. I hope it’s clear but if not, feel free to message me (mostly active on Reddit as a mod of /r/ArmanDoesStuff).
//This is the Coroutine that does the magic. ALL the camera operations end up here //This script is on an empty object at point 0,0,0 (it never moves, only rotates), and the camera is a child of this object. IEnumerator FocusCamCroute(Transform point, float distance, float delay, float shiftAmount) { transform.parent = null; //Start fresh yield return new WaitForSeconds(delay); //Simple delay float startDist = cam.transform.position.magnitude; //distance from the center to the camera so we know where to lerp the cam hight from Quaternion originStart = transform.rotation; //original rotation so we know where to lerp the rotation from //This checks if there is a point to focus on, or if it should just look at the centre. The latter is quite simple, just the regular focus but with default values. Skip to "else" for a more detailed look if (point == null) { float t = 0; while (t < 1) { transform.rotation = Quaternion.Lerp(originStart, Quaternion.LookRotation(-Vector3.forward), t); cam.transform.position = transform.forward * (Mathf.Lerp(startDist, distance, t)); cam.transform.rotation = Quaternion.Lerp(cam.transform.rotation, Quaternion.LookRotation(Vector3.forward, Vector3.up), t); t += Time.deltaTime; yield return new WaitForFixedUpdate(); } } else { float t = 0; float endDist = Vector3.Distance(Vector3.zero, point.position); //The distance from the center doesn't change so we may as well calculate the final distance now, as opposed to in the loop Vector3 direction = point.up + (point.right * 0.75f); //offset the point slightly so we can orbit at an angle. This point moves over the course of the focus but it's negligible. while (t < 1) { //Works by having the camera on a "stick" so we lerp towards where the stick should look (the point's position) transform.rotation = Quaternion.Lerp(originStart, Quaternion.LookRotation(point.position), t); //We then lerp how far up (transform.forward) on the "stick" the camera should be cam.transform.position = (transform.forward * Mathf.Lerp(startDist, endDist, t)) + (direction * Mathf.Lerp(0, distance, t)); //Finally we lerp the rotation from the start rotation to the end rotation (the point's position minus the cam's), also have to make sure the up angle is oriented to the point's up cam.transform.rotation = Quaternion.Lerp(cam.transform.rotation, Quaternion.LookRotation(point.position - cam.transform.position, point.up), Time.deltaTime * 5); t += Time.deltaTime; //takes one second total yield return new WaitForFixedUpdate(); } //we then parent the object (and camera since it's a child of this) to the point, moving with it transform.parent = point; while(true) //keep going until a new camera call occurs and StopAllCoroutines(); is called - IMPORTANT { //orbit around the point for a cool effect transform.RotateAround(transform.parent.position, transform.parent.up, -10 * Time.deltaTime); //don't forget to update the rotation so it's always looking at it cam.transform.rotation = Quaternion.Lerp(cam.transform.rotation, Quaternion.LookRotation(point.position - cam.transform.position, point.up), Time.deltaTime * 7); yield return new WaitForFixedUpdate(); } } }