Spaces:
Runtime error
Runtime error
using Photon.Deterministic; | |
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
[ | ]|
public class CameraFollow : MonoBehaviour | |
{ | |
public Transform Target; | |
public Quantum.LayerMask OcclusionQueryMask = -1; | |
[ | ]|
float distance = 5f; | |
[ | ]|
float scrollSpeed = 1f; | |
[ | ]|
float focusRadius = 1f; | |
[ | ]|
float focusCentering = 0.5f; | |
[ | ]|
float rotationSpeed = 90f; | |
[ | ]|
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; | |
} | |
} | |
} | |