Hello.
I’m trying to make my camera zoom in to my character when collide with the terrain.
I know that I should use Physics.Linecast to set my camera origin and my character’s position.
But I’m stuck at coding. I need help.
Here is my code.
The code is a camera that follows a player.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraScript : MonoBehaviour {
public Transform lookAt;
public Transform camTransform;
private const float Y_ANGLE_MIN = 5.0F;
private const float Y_ANGLE_MAX = 50.0F;
private Camera cam;
private float distance = 20.0f;
private float currentX = 0.0f;
private float currentY = 0.0f;
private float sensivityX = 4.0f;
private float sensivityY = 1.0f;
private void Start()
{
camTransform = transform;
cam = Camera.main;
}
private void Update()
{
currentX += Input.GetAxis ("Mouse X");
currentY += Input.GetAxis ("Mouse Y");
currentY = Mathf.Clamp (currentY, Y_ANGLE_MIN, Y_ANGLE_MAX);
}
private void LateUpdate()
{
Vector3 dir = new Vector3 (0, 0, -distance);
Quaternion rotation = Quaternion.Euler (currentY, currentX, 0);
camTransform.position = lookAt.position + rotation * dir;
camTransform.LookAt (lookAt.position);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraOrbitControl : MonoBehaviour {
public GameObject target;
public float distance = 5.0f;
public float sensitivityX = 20.0f;
public float sensitivityY = 20.0f;
public float yMinLimit = -30;
public float yMaxLimit = 75;
public float minimumDistance = 1f;
public float maximumDistance = 50f;
public float pushDamping = .01f;
private float currentDistance;
private bool hasHit;
private Vector3 hitPoint;
private Vector3 hitNormal;
private float hitDistance;
private float hitTimer;
private float clippedDistance;
private float currentX = 0.0f;
private float currentY = 0.0f;
public float cameraSmoothing = 0.2f;
private float currentSmoothing;
private bool forcingSmooth;
private float xSmooth = 0.0f;
private float ySmooth = 0.0f;
private float xVelocity = 0.0f;
private float yVelocity = 0.0f;
void Start () {
currentDistance = distance;
currentSmoothing = cameraSmoothing;
}
public void ForceSmoothing() {
currentSmoothing = 0f;
forcingSmooth = true;
}
void Update ()
{
if (forcingSmooth) {
currentSmoothing += Time.deltaTime / 100f;
Mathf.Clamp (currentSmoothing, 0, 1);
if (currentSmoothing >= cameraSmoothing) {
currentSmoothing = cameraSmoothing;
forcingSmooth = false;
}
}
if (target)
{
currentX += Input.GetAxis("Mouse X") * sensitivityX;
currentY += Input.GetAxis("Mouse Y") * sensitivityY;
currentY = Mathf.Clamp(currentY, yMinLimit, yMaxLimit);
xSmooth = Mathf.SmoothDamp(xSmooth, currentX, ref xVelocity, currentSmoothing);
ySmooth = Mathf.SmoothDamp(ySmooth, currentY, ref yVelocity, currentSmoothing);
float posOrNeg = Input.GetAxis ("Mouse ScrollWheel");
float wheelDistance = distance - posOrNeg * distance;
if (wheelDistance < maximumDistance) {
if (posOrNeg > 0) {
distance = Mathf.Clamp (wheelDistance, minimumDistance, maximumDistance);
}
}
if (wheelDistance > minimumDistance) {
if (posOrNeg < 0) {
distance = Mathf.Clamp (wheelDistance, minimumDistance, maximumDistance);
}
}
RaycastHit hit;
int layermask = ~((1 << 9) | (1 << 8)) ;
float smoothOverride = currentSmoothing;
if (Physics.Raycast (target.transform.position, transform.position - target.transform.position, out hit, maximumDistance, layermask)) {
hasHit = true;
hitPoint = hit.point;
hitDistance = hit.distance;
forcingSmooth = true;
clippedDistance = hit.distance;
} else {
clippedDistance = currentDistance;
hasHit = false;
}
if (currentDistance > clippedDistance) {
distance = Mathf.Lerp (distance, clippedDistance, smoothOverride * pushDamping);
currentDistance = Mathf.Lerp (currentDistance, clippedDistance, smoothOverride);
} else {
currentDistance = Mathf.Lerp (currentDistance, distance, smoothOverride);
}
transform.localRotation = Quaternion.Euler(ySmooth, xSmooth, 0);
if (hasHit) {
transform.position = Vector3.Lerp (transform.position, transform.rotation * new Vector3 (0.0f, 0.0f, -currentDistance) + target.transform.position, smoothOverride * 5f) + hitNormal * .5f;
} else {
transform.position = Vector3.Lerp(transform.position,transform.rotation * new Vector3(0.0f, 0.0f, -currentDistance) + target.transform.position,smoothOverride * 5f);
}
}
}
}
@Paincide I finally have it perfect! It rotates around the object (should be both parent object and set to target in the editor view). This is based entirely on the targets up direction too, so if you rotate the camera will rotate. You can always parent a Rig to follow the target object without rotation to fix this (ie: if your object is a ball, you obviously don’t want the camera to roll with it).
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraScript : MonoBehaviour {
public Transform lookAt;
public Transform camTransform;
private const float Y_ANGLE_MIN = 0.0F;
private const float Y_ANGLE_MAX = 60.0F;
private Camera cam;
public float cameraWidth = 5f;
public float minimumDistance = 20f;
public float maximumDistance = 20f;
public float cameraSmoothing = 5f;
public float pushDamping = 1f;
private float clippedDistance;
private float currentDistance;
private float distance = 20.0f;
private float currentX = 0.0f;
private float currentY = 0.0f;
private float sensivityX = 4.0f;
private float sensivityY = 1.0f;
private void Start()
{
camTransform = transform;
cam = Camera.main;
}
private void Update()
{
currentX += Input.GetAxis ("Mouse X");
currentY += Input.GetAxis ("Mouse Y");
currentY = Mathf.Clamp (currentY, Y_ANGLE_MIN, Y_ANGLE_MAX);
}
private void LateUpdate()
{
Vector3 dir = new Vector3 (0, 0, -currentDistance);
Quaternion rotation = Quaternion.Euler (currentY, currentX, 0);
camTransform.position = Vector3.Lerp(camTransform.position,lookAt.position + rotation * dir,cameraSmoothing);
camTransform.LookAt(lookAt.position);
RaycastHit hit;
int layermask = ~(1<<9);
if (Physics.Linecast (lookAt.position, transform.position, out hit, layermask))
{
if (hit.distance < clippedDistance - .1f && hit.distance > minimumDistance) clippedDistance = hit.distance - cameraWidth;
}
else
{
clippedDistance = distance;
}
if (distance > clippedDistance) {
currentDistance = Mathf.Lerp (currentDistance, Mathf.Clamp (clippedDistance, minimumDistance, maximumDistance), cameraSmoothing);
distance = Mathf.Lerp (distance, clippedDistance, cameraSmoothing * pushDamping);
}
else
{
currentDistance = Mathf.Lerp (currentDistance, Mathf.Clamp (distance, minimumDistance, maximumDistance), cameraSmoothing);
}
}
}
First of all, thanks for the kind reply.
I tested all kind of stuff. I changed all kind of values. I changed the center of my model. I changed the parent of my gameobject. I changed position to 0,0,0 of my gameobject. I double checked that my script is in my camera. I checked the layers twice and checked only my player is layered in 9(which is player layer). I changed the script as you said and added the line you told me. The camera zooms really cool and well, but after it zooms in, it never zoom out. If I change my minimum to 1~19 and maximum to 20, it always zoom in and never zoom out. I tried to set lower maximum and higher maximum too. But it never zoom out. Can you suggest me any more solutions?