212 lines
5.1 KiB
C#
212 lines
5.1 KiB
C#
using System;
|
|
using UnityEngine;
|
|
|
|
[Serializable]
|
|
public class ThirdPersonCamera : MonoBehaviour
|
|
{
|
|
public Transform cameraTransform;
|
|
|
|
private Transform _target;
|
|
|
|
public float distance;
|
|
|
|
public float height;
|
|
|
|
public float angularSmoothLag;
|
|
|
|
public float angularMaxSpeed;
|
|
|
|
public float heightSmoothLag;
|
|
|
|
public float snapSmoothLag;
|
|
|
|
public float snapMaxSpeed;
|
|
|
|
public float clampHeadPositionScreenSpace;
|
|
|
|
public float lockCameraTimeout;
|
|
|
|
private Vector3 headOffset;
|
|
|
|
private Vector3 centerOffset;
|
|
|
|
private float heightVelocity;
|
|
|
|
private float angleVelocity;
|
|
|
|
private bool snap;
|
|
|
|
private ThirdPersonController controller;
|
|
|
|
private float targetHeight;
|
|
|
|
public ThirdPersonCamera()
|
|
{
|
|
distance = 7f;
|
|
height = 3f;
|
|
angularSmoothLag = 0.3f;
|
|
angularMaxSpeed = 15f;
|
|
heightSmoothLag = 0.3f;
|
|
snapSmoothLag = 0.2f;
|
|
snapMaxSpeed = 720f;
|
|
clampHeadPositionScreenSpace = 0.75f;
|
|
lockCameraTimeout = 0.2f;
|
|
headOffset = Vector3.zero;
|
|
centerOffset = Vector3.zero;
|
|
targetHeight = 100000f;
|
|
}
|
|
|
|
public virtual void Awake()
|
|
{
|
|
if (!cameraTransform && (bool)Camera.main)
|
|
{
|
|
cameraTransform = Camera.main.transform;
|
|
}
|
|
if (!cameraTransform)
|
|
{
|
|
Debug.Log("Please assign a camera to the ThirdPersonCamera script.");
|
|
enabled = false;
|
|
}
|
|
_target = transform;
|
|
if ((bool)_target)
|
|
{
|
|
controller = (ThirdPersonController)_target.GetComponent(typeof(ThirdPersonController));
|
|
}
|
|
if ((bool)controller)
|
|
{
|
|
CharacterController characterController = (CharacterController)_target.GetComponent<Collider>();
|
|
centerOffset = characterController.bounds.center - _target.position;
|
|
headOffset = centerOffset;
|
|
headOffset.y = characterController.bounds.max.y - _target.position.y;
|
|
}
|
|
else
|
|
{
|
|
Debug.Log("Please assign a target to the camera that has a ThirdPersonController script attached.");
|
|
}
|
|
Cut(_target, centerOffset);
|
|
}
|
|
|
|
public virtual void DebugDrawStuff()
|
|
{
|
|
Debug.DrawLine(_target.position, _target.position + headOffset);
|
|
}
|
|
|
|
public virtual float AngleDistance(float a, float b)
|
|
{
|
|
a = Mathf.Repeat(a, 360f);
|
|
b = Mathf.Repeat(b, 360f);
|
|
return Mathf.Abs(b - a);
|
|
}
|
|
|
|
public virtual void Apply(Transform dummyTarget, Vector3 dummyCenter)
|
|
{
|
|
if (!controller)
|
|
{
|
|
return;
|
|
}
|
|
Vector3 vector = _target.position + centerOffset;
|
|
Vector3 headPos = _target.position + headOffset;
|
|
float y = _target.eulerAngles.y;
|
|
float y2 = cameraTransform.eulerAngles.y;
|
|
float num = y;
|
|
if (Input.GetButton("Fire2"))
|
|
{
|
|
snap = true;
|
|
}
|
|
if (snap)
|
|
{
|
|
if (!(AngleDistance(y2, y) >= 3f))
|
|
{
|
|
snap = false;
|
|
}
|
|
y2 = Mathf.SmoothDampAngle(y2, num, ref angleVelocity, snapSmoothLag, snapMaxSpeed);
|
|
}
|
|
else
|
|
{
|
|
if (!(controller.GetLockCameraTimer() >= lockCameraTimeout))
|
|
{
|
|
num = y2;
|
|
}
|
|
if (!(AngleDistance(y2, num) <= 160f) && controller.IsMovingBackwards())
|
|
{
|
|
num += 180f;
|
|
}
|
|
y2 = Mathf.SmoothDampAngle(y2, num, ref angleVelocity, angularSmoothLag, angularMaxSpeed);
|
|
}
|
|
if (controller.IsJumping())
|
|
{
|
|
float num2 = vector.y + height;
|
|
if (num2 < targetHeight || !(num2 - targetHeight <= 5f))
|
|
{
|
|
targetHeight = vector.y + height;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
targetHeight = vector.y + height;
|
|
}
|
|
float y3 = cameraTransform.position.y;
|
|
y3 = Mathf.SmoothDamp(y3, targetHeight, ref heightVelocity, heightSmoothLag);
|
|
Quaternion quaternion = Quaternion.Euler(0f, y2, 0f);
|
|
cameraTransform.position = vector;
|
|
cameraTransform.position += quaternion * Vector3.back * distance;
|
|
float y4 = y3;
|
|
Vector3 position = cameraTransform.position;
|
|
float num3 = (position.y = y4);
|
|
Vector3 vector2 = (cameraTransform.position = position);
|
|
SetUpRotation(vector, headPos);
|
|
}
|
|
|
|
public virtual void LateUpdate()
|
|
{
|
|
Apply(transform, Vector3.zero);
|
|
}
|
|
|
|
public virtual void Cut(Transform dummyTarget, Vector3 dummyCenter)
|
|
{
|
|
float num = heightSmoothLag;
|
|
float num2 = snapMaxSpeed;
|
|
float num3 = snapSmoothLag;
|
|
snapMaxSpeed = 10000f;
|
|
snapSmoothLag = 0.001f;
|
|
heightSmoothLag = 0.001f;
|
|
snap = true;
|
|
Apply(transform, Vector3.zero);
|
|
heightSmoothLag = num;
|
|
snapMaxSpeed = num2;
|
|
snapSmoothLag = num3;
|
|
}
|
|
|
|
public virtual void SetUpRotation(Vector3 centerPos, Vector3 headPos)
|
|
{
|
|
Vector3 position = cameraTransform.position;
|
|
Vector3 vector = centerPos - position;
|
|
Quaternion quaternion = Quaternion.LookRotation(new Vector3(vector.x, 0f, vector.z));
|
|
Vector3 forward = Vector3.forward * distance + Vector3.down * height;
|
|
cameraTransform.rotation = quaternion * Quaternion.LookRotation(forward);
|
|
Ray ray = cameraTransform.GetComponent<Camera>().ViewportPointToRay(new Vector3(0.5f, 0.5f, 1f));
|
|
Ray ray2 = cameraTransform.GetComponent<Camera>().ViewportPointToRay(new Vector3(0.5f, clampHeadPositionScreenSpace, 1f));
|
|
Vector3 point = ray.GetPoint(distance);
|
|
Vector3 point2 = ray2.GetPoint(distance);
|
|
float num = Vector3.Angle(ray.direction, ray2.direction);
|
|
float num2 = num / (point.y - point2.y);
|
|
float num3 = num2 * (point.y - centerPos.y);
|
|
if (!(num3 >= num))
|
|
{
|
|
num3 = 0f;
|
|
return;
|
|
}
|
|
num3 -= num;
|
|
cameraTransform.rotation *= Quaternion.Euler(0f - num3, 0f, 0f);
|
|
}
|
|
|
|
public virtual Vector3 GetCenterOffset()
|
|
{
|
|
return centerOffset;
|
|
}
|
|
|
|
public virtual void Main()
|
|
{
|
|
}
|
|
}
|