custom-chatbot / data /CameraFollow.cs
fastx's picture
Upload 84 files
ce81a16
raw
history blame
4.16 kB
using Photon.Deterministic;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Camera))]
public class CameraFollow : MonoBehaviour
{
public Transform Target;
public Quantum.LayerMask OcclusionQueryMask = -1;
[SerializeField, Range(2f, 15f)]
float distance = 5f;
[SerializeField, Range(0.1f, 5f)]
float scrollSpeed = 1f;
[SerializeField, Min(0f)]
float focusRadius = 1f;
[SerializeField, Range(0f, 1f)]
float focusCentering = 0.5f;
[SerializeField, Range(1f, 360f)]
float rotationSpeed = 90f;
[SerializeField, Range(-30f, 89f)]
float minVerticalAngle = -30f, maxVerticalAngle = 60f;
Vector3 focusPoint;
Vector2 orbitAngles = new Vector2(45f, 0f);
private Camera _camera;
void Awake()
{
//focusPoint = focus.position;
transform.localRotation = Quaternion.Euler(orbitAngles);
_camera = GetComponent<Camera>();
}
void LateUpdate()
{
if (Target == null) return;
UpdateDistance();
UpdateFocusPoint();
Quaternion lookRotation;
if (ManualRotation())
{
ConstrainAngles();
lookRotation = Quaternion.Euler(orbitAngles);
}
else
{
lookRotation = transform.localRotation;
}
Vector3 lookDirection = lookRotation * Vector3.forward;
Vector3 lookPosition = focusPoint - lookDirection * distance;
if (Cast(focusPoint, lookRotation, -lookDirection, out var hitDistance, distance - _camera.nearClipPlane))
{
lookPosition = focusPoint - lookDirection * (hitDistance + _camera.nearClipPlane);
}
transform.SetPositionAndRotation(lookPosition, lookRotation);
}
private unsafe bool Cast(Vector3 origin, Quaternion rotation, Vector3 direction, out float hitDistance, float distance)
{
hitDistance = 0;
var frame = QuantumRunner.Default?.Game?.Frames.Verified;
if (frame != null)
{
var shape = Quantum.Shape3D.CreateBox(CameraPlaneExtends.ToFPVector3());
var options = Quantum.QueryOptions.ComputeDetailedInfo | Quantum.QueryOptions.HitAll;
var hit = frame.Physics3D.ShapeCast(origin.ToFPVector3(), rotation.ToFPQuaternion(), &shape, (direction * distance).ToFPVector3(), OcclusionQueryMask, options);
if (hit.HasValue)
{
hitDistance = (origin - hit.Value.Point.ToUnityVector3()).magnitude;
return true;
}
}
return false;
}
Vector3 CameraPlaneExtends
{
get
{
Vector3 halfExtends;
halfExtends.y =
_camera.nearClipPlane *
Mathf.Tan(0.5f * Mathf.Deg2Rad * _camera.fieldOfView) * 1.25f;
halfExtends.x = halfExtends.y * _camera.aspect;
halfExtends.z = 0.01f;
return halfExtends;
}
}
void UpdateDistance()
{
distance += Input.GetAxisRaw("Mouse ScrollWheel") * scrollSpeed;
distance = Mathf.Clamp(distance, 2, 15);
}
bool ManualRotation()
{
Vector2 input = new Vector2(
-Input.GetAxis("Mouse Y"),
Input.GetAxis("Mouse X")
);
const float e = 0.001f;
if (input.x < e || input.x > e || input.y < e || input.y > e)
{
orbitAngles += rotationSpeed * Time.unscaledDeltaTime * input;
return true;
}
return false;
}
void UpdateFocusPoint()
{
Vector3 targetPoint = Target.position;
if (focusRadius > 0f)
{
float distance = Vector3.Distance(targetPoint, focusPoint);
float t = 1f;
if (distance > 0.01f && focusCentering > 0f)
{
t = Mathf.Pow(1f - focusCentering, Time.unscaledDeltaTime);
}
if (distance > focusRadius)
{
t = Mathf.Min(t, focusRadius / distance);
}
focusPoint = Vector3.Lerp(targetPoint, focusPoint, t);
}
else
{
focusPoint = targetPoint;
}
}
void ConstrainAngles()
{
orbitAngles.x =
Mathf.Clamp(orbitAngles.x, minVerticalAngle, maxVerticalAngle);
if (orbitAngles.y < 0f)
{
orbitAngles.y += 360f;
}
else if (orbitAngles.y >= 360f)
{
orbitAngles.y -= 360f;
}
}
void OnValidate()
{
if (maxVerticalAngle < minVerticalAngle)
{
maxVerticalAngle = minVerticalAngle;
}
}
}