mirror of
https://github.com/nothke/quality-control.git
synced 2025-09-02 08:33:42 +00:00
Added KCC
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace KinematicCharacterController.Examples
|
||||
{
|
||||
public class ExampleCharacterCamera : MonoBehaviour
|
||||
{
|
||||
[Header("Framing")]
|
||||
public Camera Camera;
|
||||
public Vector2 FollowPointFraming = new Vector2(0f, 0f);
|
||||
public float FollowingSharpness = 10000f;
|
||||
|
||||
[Header("Distance")]
|
||||
public float DefaultDistance = 6f;
|
||||
public float MinDistance = 0f;
|
||||
public float MaxDistance = 10f;
|
||||
public float DistanceMovementSpeed = 5f;
|
||||
public float DistanceMovementSharpness = 10f;
|
||||
|
||||
[Header("Rotation")]
|
||||
public bool InvertX = false;
|
||||
public bool InvertY = false;
|
||||
[Range(-90f, 90f)]
|
||||
public float DefaultVerticalAngle = 20f;
|
||||
[Range(-90f, 90f)]
|
||||
public float MinVerticalAngle = -90f;
|
||||
[Range(-90f, 90f)]
|
||||
public float MaxVerticalAngle = 90f;
|
||||
public float RotationSpeed = 1f;
|
||||
public float RotationSharpness = 10000f;
|
||||
public bool RotateWithPhysicsMover = false;
|
||||
|
||||
[Header("Obstruction")]
|
||||
public float ObstructionCheckRadius = 0.2f;
|
||||
public LayerMask ObstructionLayers = -1;
|
||||
public float ObstructionSharpness = 10000f;
|
||||
public List<Collider> IgnoredColliders = new List<Collider>();
|
||||
|
||||
public Transform Transform { get; private set; }
|
||||
public Transform FollowTransform { get; private set; }
|
||||
|
||||
public Vector3 PlanarDirection { get; set; }
|
||||
public float TargetDistance { get; set; }
|
||||
|
||||
private bool _distanceIsObstructed;
|
||||
private float _currentDistance;
|
||||
private float _targetVerticalAngle;
|
||||
private RaycastHit _obstructionHit;
|
||||
private int _obstructionCount;
|
||||
private RaycastHit[] _obstructions = new RaycastHit[MaxObstructions];
|
||||
private float _obstructionTime;
|
||||
private Vector3 _currentFollowPosition;
|
||||
|
||||
private const int MaxObstructions = 32;
|
||||
|
||||
void OnValidate()
|
||||
{
|
||||
DefaultDistance = Mathf.Clamp(DefaultDistance, MinDistance, MaxDistance);
|
||||
DefaultVerticalAngle = Mathf.Clamp(DefaultVerticalAngle, MinVerticalAngle, MaxVerticalAngle);
|
||||
}
|
||||
|
||||
void Awake()
|
||||
{
|
||||
Transform = this.transform;
|
||||
|
||||
_currentDistance = DefaultDistance;
|
||||
TargetDistance = _currentDistance;
|
||||
|
||||
_targetVerticalAngle = 0f;
|
||||
|
||||
PlanarDirection = Vector3.forward;
|
||||
}
|
||||
|
||||
// Set the transform that the camera will orbit around
|
||||
public void SetFollowTransform(Transform t)
|
||||
{
|
||||
FollowTransform = t;
|
||||
PlanarDirection = FollowTransform.forward;
|
||||
_currentFollowPosition = FollowTransform.position;
|
||||
}
|
||||
|
||||
public void UpdateWithInput(float deltaTime, float zoomInput, Vector3 rotationInput)
|
||||
{
|
||||
if (FollowTransform)
|
||||
{
|
||||
if (InvertX)
|
||||
{
|
||||
rotationInput.x *= -1f;
|
||||
}
|
||||
if (InvertY)
|
||||
{
|
||||
rotationInput.y *= -1f;
|
||||
}
|
||||
|
||||
// Process rotation input
|
||||
Quaternion rotationFromInput = Quaternion.Euler(FollowTransform.up * (rotationInput.x * RotationSpeed));
|
||||
PlanarDirection = rotationFromInput * PlanarDirection;
|
||||
PlanarDirection = Vector3.Cross(FollowTransform.up, Vector3.Cross(PlanarDirection, FollowTransform.up));
|
||||
Quaternion planarRot = Quaternion.LookRotation(PlanarDirection, FollowTransform.up);
|
||||
|
||||
_targetVerticalAngle -= (rotationInput.y * RotationSpeed);
|
||||
_targetVerticalAngle = Mathf.Clamp(_targetVerticalAngle, MinVerticalAngle, MaxVerticalAngle);
|
||||
Quaternion verticalRot = Quaternion.Euler(_targetVerticalAngle, 0, 0);
|
||||
Quaternion targetRotation = Quaternion.Slerp(Transform.rotation, planarRot * verticalRot, 1f - Mathf.Exp(-RotationSharpness * deltaTime));
|
||||
|
||||
// Apply rotation
|
||||
Transform.rotation = targetRotation;
|
||||
|
||||
// Process distance input
|
||||
if (_distanceIsObstructed && Mathf.Abs(zoomInput) > 0f)
|
||||
{
|
||||
TargetDistance = _currentDistance;
|
||||
}
|
||||
TargetDistance += zoomInput * DistanceMovementSpeed;
|
||||
TargetDistance = Mathf.Clamp(TargetDistance, MinDistance, MaxDistance);
|
||||
|
||||
// Find the smoothed follow position
|
||||
_currentFollowPosition = Vector3.Lerp(_currentFollowPosition, FollowTransform.position, 1f - Mathf.Exp(-FollowingSharpness * deltaTime));
|
||||
|
||||
// Handle obstructions
|
||||
{
|
||||
RaycastHit closestHit = new RaycastHit();
|
||||
closestHit.distance = Mathf.Infinity;
|
||||
_obstructionCount = Physics.SphereCastNonAlloc(_currentFollowPosition, ObstructionCheckRadius, -Transform.forward, _obstructions, TargetDistance, ObstructionLayers, QueryTriggerInteraction.Ignore);
|
||||
for (int i = 0; i < _obstructionCount; i++)
|
||||
{
|
||||
bool isIgnored = false;
|
||||
for (int j = 0; j < IgnoredColliders.Count; j++)
|
||||
{
|
||||
if (IgnoredColliders[j] == _obstructions[i].collider)
|
||||
{
|
||||
isIgnored = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < IgnoredColliders.Count; j++)
|
||||
{
|
||||
if (IgnoredColliders[j] == _obstructions[i].collider)
|
||||
{
|
||||
isIgnored = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isIgnored && _obstructions[i].distance < closestHit.distance && _obstructions[i].distance > 0)
|
||||
{
|
||||
closestHit = _obstructions[i];
|
||||
}
|
||||
}
|
||||
|
||||
// If obstructions detecter
|
||||
if (closestHit.distance < Mathf.Infinity)
|
||||
{
|
||||
_distanceIsObstructed = true;
|
||||
_currentDistance = Mathf.Lerp(_currentDistance, closestHit.distance, 1 - Mathf.Exp(-ObstructionSharpness * deltaTime));
|
||||
}
|
||||
// If no obstruction
|
||||
else
|
||||
{
|
||||
_distanceIsObstructed = false;
|
||||
_currentDistance = Mathf.Lerp(_currentDistance, TargetDistance, 1 - Mathf.Exp(-DistanceMovementSharpness * deltaTime));
|
||||
}
|
||||
}
|
||||
|
||||
// Find the smoothed camera orbit position
|
||||
Vector3 targetPosition = _currentFollowPosition - ((targetRotation * Vector3.forward) * _currentDistance);
|
||||
|
||||
// Handle framing
|
||||
targetPosition += Transform.right * FollowPointFraming.x;
|
||||
targetPosition += Transform.up * FollowPointFraming.y;
|
||||
|
||||
// Apply position
|
||||
Transform.position = targetPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user