So I’m trying to create a follow camera that basically moves with the character when necessary, and can also rotate around the character. When there’s no camera input, the camera basically just tracks the character, moving closer when needed.
Where as my Orbit script uses the Goal vector to determine the camera’s position at all times…
(Goal.x based on Mouse X, rotates around Y axis, goal.y based on Mouse Y, rotates around the “X” axis of what the camera sees…)
... Quaternion.Euler(goal.y, goal.x, 0);
Vector3 position = targetPoint + rotation * new Vector3(0,0,-goal.z);
RaycastHit hit;
if (Physics.Linecast (targetPoint,position, out hit)) {
position = targetPoint + Vector3.ClampMagnitude(position-targetPoint,hit.distance);
}
transform.rotation = rotation;
transform.position = position;
...
… I want my Follow script to do something similar, but only rotate around Y when input acts on it; like an addition. Therefor, instead of goal.x always moving the camera around the Y axis to reach goal.x, I want to set goal.x to what it is -currently at-, + input.x.
The only problem is, I can’t figure out how to meaningfully determine how far around the Y axis the camera’s position is at any given point. I’ve tried all sorts of crazy quaternion, vector, and transform calculations, but nothing I’ve done works.
I am workin on it, but dont have time to finish it right now. Here is a unedited untested version of hte mix of the orbit and follow cameras.
When I get done, I will present it along with a working Minimalistic WowCamera. (its the same thing)
using UnityEngine;
using System.Collections;
public class example : MonoBehaviour {
public Transform target; // target to follow
public float distance = 20; // initial distance
public Vector2 XYMouseSpeed = new Vector2(120, 120); // clamping for scroll speed
public Vector2 minMaxDistance = new Vector2(10, 100); // clamping for scroll
public Vector2 minMaxYClamp = new Vector2(-60, 60); // clamping for Y
public float scrollSpeed = 10; // scroll speed for the mouse
public float damping = 3; // damping for current to goal
private Vector3 goal = Vector3.zero; // the goal target
private Vector3 current = Vector3.zero; // hold the current target
public float releaseTimeDelay = 2; // delay to start following
private float lastRightDown = 0; // hold the last time we had the button down
void Start(){
// gather the intial variables
Vector3 angles = transform.eulerAngles;
goal.x = angles.y;
goal.y = angles.x;
goal.z = distance;
// set the goal and distance to the same so we dont start off wierd
current = goal;
}
void LateUpdate(){
// gather the target point
Vector3 targetPoint = Vector3.zero;
if(target) targetPoint = target.position;
// only work when the right mouse button is down
if(Input.GetMouseButton(1)){
Screen.showCursor = false;
// do mouse movement
goal.x += Input.GetAxis("Mouse X") * XYMouseSpeed.x * 0.02;
goal.y -= Input.GetAxis("Mouse Y") * XYMouseSpeed.y * 0.02;
goal.y = ClampAngle(goal.y, minMaxYClamp.x, minMaxYClamp.y);
// used to make it delay following
lastRightDown = Time.time;
} else {
Screen.showCursor = true;
// if not, then we act like a follower
if(Time.time > lastRightDown + releaseTimeDelay){
Vector3 angles = transform.eulerAngles;
goal.x = angles.y;
}
}
// set the goal.z with scroll wheel input and clamp it
goal.z += Input.GetAxis("Mouse ScrollWheel") * scrollSpeed;
gaol.z = Mathf.Clamp(goal.z, minMaxDistance.x, minMaxDistance.y);
// lerp the current to the goal
current = Mathf.Lerp(current, goal, damping * Time.deltaTime);
// set the rotation from the current
Quaternion rotation = Quaternion.Euler(current.y, current.x, 0);
Vector3 direction = rotation * new Vector3(0,0,-1);
// get anything that would get in the way of the camera
RaycastHit hit;
if (Physics.Linecast(targetPoint,targetPoint + direction * current.z, out hit)) {
current.z = Mathf.Clamp(hit.distance - 1, 0, minMaxDistance.y);
}
// set the position now based on the new current.z and direction
Vector3 position = targetPoint + direction * current.z;
transform.position = position;
transform.rotation = rotation;
}
private static float ClampAngle (float angle, float min, float max) {
if (angle < -360) angle += 360;
if (angle > 360) angle -= 360;
return Mathf.Clamp(angle, min, max);
}
}
Hey, thanks for your input! This has been really hellish to work on so far, so your help is greatly appreciated. Will mess around with it some in the mean time.
EDIT: I used your code both as-is and also stripped down to bare-bones minimum, and both behaved similarly to my original type.
However, this led me to do more testing, and I came to realize that the cameras in games I play aren’t the Follow mechanics + the Input mechanics, but that Input overrides the Follow. This will make things dramatically easier!
Essentially at this point, I’ll make a simple follow cam which functions on Y-axis and Y-rot separately. If any input happens, I will override the follow functions with an Orbit function.