Last active
June 28, 2023 05:20
-
-
Save pppoe252110/b2f512b5efb4ac71c1de04c6305cc699 to your computer and use it in GitHub Desktop.
Third Person Camera Controller
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.Linq; | |
using UnityEngine; | |
using UnityEngine.Serialization; | |
public class ThirdPersonCameraController : MonoBehaviour | |
{ | |
[SerializeField, FormerlySerializedAs("Camera Target")] private Transform target; | |
[Header("View")] | |
[SerializeField, FormerlySerializedAs("View Sensitivity")] private float _viewSensitivity = 3f; | |
[SerializeField, FormerlySerializedAs("Scroll Sensitivity")] private float _scrollSensitivity = 3f; | |
[SerializeField, FormerlySerializedAs("Maximum Verical Angle")] private float _maxVericalAngle = 70f; | |
[SerializeField, FormerlySerializedAs("Minimum Verical Angle")] private float _minVericalAngle = -30f; | |
[SerializeField, FormerlySerializedAs("Maximum Distance")] private float _maxDistance = 5f; | |
[SerializeField, FormerlySerializedAs("Minimum Distance")] private float _minDistance = 3f; | |
[SerializeField, FormerlySerializedAs("Forward Offset")] private float _forwardOffset = 0.1f; | |
[SerializeField, FormerlySerializedAs("View Offset")] private Vector2 _viewOffset = new Vector2(0.5f, 0); | |
[Header("Rays")] | |
[SerializeField, FormerlySerializedAs("Rays Distance From Center")] private float _raysDistance = 0.2f; | |
[SerializeField, FormerlySerializedAs("Rays")] private Vector2[] _rays; | |
[SerializeField, FormerlySerializedAs("Ignore Layer")] private LayerMask _ignoreLayer; | |
private float currentDistance = 5f; | |
public void Reset() | |
{ | |
_rays = new Vector2[9]; | |
for (int i = 0; i < _rays.Length; i++) | |
{ | |
_rays[i] = new Vector2(Mathf.Cos(i * 45f * Mathf.Deg2Rad), Mathf.Sin(i * 45f * Mathf.Deg2Rad)); | |
} | |
_rays[8] = Vector2.zero; | |
} | |
private void Update() | |
{ | |
currentDistance = Mathf.Clamp(currentDistance - Input.GetAxis("Mouse ScrollWheel") * _scrollSensitivity, _minDistance, _maxDistance); | |
transform.rotation = Quaternion.Euler(Mathf.Clamp(FixAngle(transform.rotation.eulerAngles.x - Input.GetAxis("Mouse Y") * _viewSensitivity), _minVericalAngle, _maxVericalAngle), transform.eulerAngles.y + Input.GetAxis("Mouse X") * _viewSensitivity, transform.eulerAngles.z); | |
} | |
private void LateUpdate() | |
{ | |
List<RaycastHit> hits = new List<RaycastHit>(); | |
Vector3 targetDir = GetTargetDirection(); | |
for (int i = 0; i < _rays.Length; i++) | |
{ | |
var rayPos = GetRayPos(i); | |
if (Physics.Raycast(rayPos, targetDir, out var hit, currentDistance, ~_ignoreLayer)) | |
{ | |
hits.Add(hit); | |
} | |
} | |
if (hits.Count > 0) | |
{ | |
var closest = hits.Min(a => a.distance); | |
UpdateView(closest); | |
} | |
else | |
{ | |
UpdateView(currentDistance); | |
} | |
} | |
public Vector3 GetRayPos(int i) | |
{ | |
return target.position + transform.rotation * new Vector2(_rays[i].x * _raysDistance, _rays[i].y * _raysDistance); | |
} | |
public float FixAngle(float angle) | |
{ | |
if (angle > 180) | |
return angle - 360f; | |
if (angle < -180) | |
return angle + 360f; | |
return angle; | |
} | |
public Vector3 GetTargetPosition() | |
{ | |
return transform.rotation * new Vector3(_viewOffset.x, _viewOffset.y, -_maxDistance) + target.position; | |
} | |
public Vector3 GetTargetDirection() | |
{ | |
var targetDir = GetTargetPosition() - target.position; | |
targetDir.Normalize(); | |
return targetDir; | |
} | |
public void UpdateView(float distance) | |
{ | |
Vector3 targetDir = GetTargetDirection(); | |
transform.position = targetDir * distance + target.position + transform.forward * _forwardOffset; | |
} | |
#if UNITY_EDITOR | |
private void OnDrawGizmos() | |
{ | |
for (int i = 0; i < _rays.Length; i++) | |
{ | |
var rayPos = GetRayPos(i); | |
Gizmos.DrawRay(rayPos, transform.rotation * new Vector3(_viewOffset.x, _viewOffset.y, -currentDistance)); | |
} | |
} | |
#endif | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment