Net_Ease_Dome/Assets/Scripts/Input/CameraController.cs

510 lines
17 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
using System.Collections.Generic;
public class CameraController :MonoBehaviour
{
public bool m_isScale = true;
#region fpp
/// <summary>
/// 转到第一人称视角
/// </summary>
public bool m_fpp;
/// <summary>
/// 第一人称视角偏差
/// </summary>
public Vector3 m_fppOffset;
/// <summary>
/// 跟随老师
/// </summary>
public bool FollowTeacher;
private bool m_followTeacher;
#endregion
public Transform Target;
public float distance = 8.0f;
public float xSpeed = 70.0f;
public float ySpeed = 50.0f;
public float yMinLimit = 0f;
public float yMaxLimit = 90f;
public float distanceMin = 8f;
public float distanceMax = 15f;
public float zoomSpeed = 0.5f;
private float x = 0.0f;
private float y = 0.0f;
private float fx = 0f;
private float fy = 0f;
private float fDistance = 0;
int m_fingerId = -1; // 当摇杆移动,控制镜头的手指
bool m_isClickUi = false;
Dictionary<int, bool> m_dicTouch = new Dictionary<int, bool>(); //key 为fingerid value为是否接触到UI
Transform m_trans;
float t = 0.2f;
public float m_minDis = 1.0f;
public bool m_isNear = false;
[Header("God Mode")]
public bool God; //上帝模式
public float GodSpeed = 10;
public float Sprint = 1.5f;
public Vector3 MinClamp = new Vector3(0,12,0);
public Vector3 MaxClamp = new Vector3(160,20,160);
public Vector2 RollClamp = new Vector2(-45, 90);
public Rigidbody _rigidbody;
// Use this for initialization
void Start()
{
_rigidbody = GetComponent<Rigidbody>();
m_trans = this.transform;
Vector3 angles = transform.eulerAngles;
x = angles.y;
y = angles.x;
fx = x;
fy = y;
UpdateRotaAndPos();
fDistance = distance;
}
void Update()
{
if (Input.touchCount == 0)//当前没有手指,全部初始化
{
m_fingerId = -1;
m_dicTouch.Clear();
}
if (Input.touchCount == 1)
{
List<int> deleteFinger = new List<int>();
foreach (var item in m_dicTouch)
{
if (item.Key != Input.GetTouch(0).fingerId)
{
deleteFinger.Add(item.Key);
}
}
//删除m_dicTouch非当前单指的item项目--》得到结果就是m_dicTouch只有当前单指或者啥也没有
for (int i = 0; i < deleteFinger.Count; i++)
{
//Debug.Log("单指:删除:" + deleteFinger[i]);
m_dicTouch.Remove(deleteFinger[i]);
}
switch (Input.GetTouch(0).phase)
{
case TouchPhase.Began:
if (EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId))
{
//Debug.Log("单指增加true" + Input.GetTouch(0).fingerId);
m_dicTouch[Input.GetTouch(0).fingerId] = true; //如果按在ui上为true
}
else
{
//Debug.Log("单指增加false" + Input.GetTouch(0).fingerId);
m_dicTouch[Input.GetTouch(0).fingerId] = false;
}
break;
case TouchPhase.Moved:
break;
case TouchPhase.Stationary:
break;
case TouchPhase.Ended:
break;
case TouchPhase.Canceled:
break;
default:
break;
}
}
if (Input.touchCount == 2)
{
List<int> deleteFinger = new List<int>();
foreach (var item in m_dicTouch)
{
bool isDelete = true;
for (int i = 0; i < Input.touchCount; i++)
{
if (item.Key == Input.touches[i].fingerId)
{
isDelete = false;
break;
}
}
if (isDelete == true)
{
deleteFinger.Add(item.Key);
}
}
//删除m_dicTouch里面非现在按下的两个手指--》得到的结果m_dicTouch里有一个现在按下手指中的0-2个
for (int i = 0; i < deleteFinger.Count; i++)
{
//Debug.Log("双指:删除:" + deleteFinger[i]);
m_dicTouch.Remove(deleteFinger[i]);
}
for (int i = 0; i < Input.touchCount; i++)
{
switch (Input.touches[i].phase)
{
case TouchPhase.Began:
if (EventSystem.current.IsPointerOverGameObject(Input.touches[i].fingerId))
{
//Debug.Log("双指增加true" + Input.touches[i].fingerId);
m_dicTouch[Input.touches[i].fingerId] = true;
}
else
{
//Debug.Log("双指增加false" + Input.touches[i].fingerId);
m_dicTouch[Input.touches[i].fingerId] = false;
}
break;
case TouchPhase.Moved:
break;
case TouchPhase.Stationary:
break;
case TouchPhase.Ended:
break;
case TouchPhase.Canceled:
break;
default:
break;
}
}
if (IsCanScale() == true && m_isScale == true)
{
Touch touchZero = Input.GetTouch(0);
Touch touchOne = Input.GetTouch(1);
// 上一帧每个点位置
Vector2 touchZeroPrevPos = touchZero.position - touchZero.deltaPosition;
Vector2 touchOnePrevPos = touchOne.position - touchOne.deltaPosition;
//上一帧两点距离的平方,不要做平方根运算,消耗大
float prevTouchDeltaMag = (touchZeroPrevPos - touchOnePrevPos).magnitude;
//这一帧两点距离的平方
float touchDeltaMag = (touchZero.position - touchOne.position).magnitude;
// Find the difference in the distances between each frame.
float deltaMagnitudeDiff = prevTouchDeltaMag - touchDeltaMag;
fDistance = Mathf.Clamp(distance + deltaMagnitudeDiff * zoomSpeed, distanceMin, distanceMax);
}
}
if (Application.isMobilePlatform == false && m_isScale == true)
{
if (Input.GetAxis("Mouse ScrollWheel") > 0)
{
fDistance = Mathf.Clamp(distance - zoomSpeed, distanceMin, distanceMax);
}
else if (Input.GetAxis("Mouse ScrollWheel") < 0)
{
fDistance = Mathf.Clamp(distance + zoomSpeed, distanceMin, distanceMax);
}
}
distance = Mathf.Lerp(distance, fDistance, 0.25f);
}
private void FixedUpdate()
{
Move();
}
private void Move()
{
if (Application.isMobilePlatform)
{
if (/*Input.GetMouseButton(1) &&*/ IsCanRotate())
{
Touch input = new Touch();
for (int i = 0; i < Input.touchCount; i++)
{
if (Input.touches[i].fingerId == m_fingerId)
{
input = Input.touches[i];//找到控制镜头移动的手指
}
}
if (God) {
if (Target)
{
if (Input.touchCount > 0 && input.phase == TouchPhase.Moved)
{
float dx = input.deltaPosition.x;
float dy = input.deltaPosition.y;
x -= dx * xSpeed * Time.deltaTime;
y += dy * ySpeed * Time.deltaTime;
y = ClampAngle(y, RollClamp.x, RollClamp.y);
}
}
}
else {
if (Input.touchCount > 0 && input.phase == TouchPhase.Moved)
{
float dx = input.deltaPosition.x;
float dy = input.deltaPosition.y;
x -= dx * xSpeed * Time.deltaTime;
y += dy * ySpeed * Time.deltaTime;
y = ClampAngle(y, yMinLimit, yMaxLimit);
}
}
}
}
else
{
if (Input.GetMouseButtonDown(1))
{
if (EventSystem.current.IsPointerOverGameObject())
{
m_isClickUi = true;
}
}
if (Input.GetMouseButtonUp(0))
{
m_isClickUi = false;
}
if (m_isClickUi == false && Input.GetMouseButton(1))
{
if (God)
{
if (Target)
{
float dx = Input.GetAxis("Mouse X");
float dy = Input.GetAxis("Mouse Y");
x += dx * xSpeed * 20 * Time.deltaTime;//*distance
y -= dy * ySpeed * 20 * Time.deltaTime;
y = ClampAngle(y, RollClamp.x, RollClamp.y);
}
}
else
{
float dx = Input.GetAxis("Mouse X");
float dy = Input.GetAxis("Mouse Y");
x += dx * xSpeed * 20 * Time.deltaTime;//*distance
y -= dy * ySpeed * 20 * Time.deltaTime;
y = ClampAngle(y, yMinLimit, yMaxLimit);
}
}
}
fx = Mathf.Lerp(fx, x, 0.2f);
fy = Mathf.Lerp(fy, y, 0.2f);
UpdateRotaAndPos();
}
void UpdateRotaAndPos()
{
if (God)
{
float godspeed = (UtilitiesInput.Sprint ? GodSpeed * Sprint : GodSpeed) * Time.deltaTime;
//transform.Translate(Vector3.forward * UtilitiesInput.Vertical * godspeed, Space.Self);
//transform.Translate(Vector3.right * UtilitiesInput.Horizontal * godspeed, Space.Self);
Vector3 dir = transform.forward * UtilitiesInput.Vertical + transform.right * UtilitiesInput.Horizontal;
GodMoveCamera(dir, godspeed);
if (UtilitiesInput.Down) transform.Translate(Vector3.down * godspeed, Space.World);
if (UtilitiesInput.Up) transform.Translate(Vector3.up * godspeed, Space.World);
Vector3 trans = transform.position;
transform.position = new Vector3(Mathf.Clamp(trans.x, MinClamp.x, MaxClamp.x), Mathf.Clamp(trans.y, MinClamp.y, MaxClamp.y), Mathf.Clamp(trans.z, MinClamp.z, MaxClamp.z));
Quaternion rotation = Quaternion.Euler(fy, fx, 0);
Vector3 negDistance = new Vector3(0.0f, 0.0f, -distance);
Vector3 position = rotation * negDistance + Target.position; //摄像头的位置为 移动后角度*距离 + 目标位置
transform.rotation = rotation;
}
else
{
if (Target)
{
bool isCurHit = false;
Quaternion rotation = Quaternion.Euler(fy, fx, 0);
Vector3 negDistance = new Vector3(0.0f, 0.0f, -distance);
Vector3 position = rotation * negDistance + Target.position; //摄像头的位置为 移动后角度*距离 + 目标位置
Vector3 canSetPos = position;
//m_trans.position = position;
//Debug.DrawLine(target.position, m_trans.position, Color.red);
//主角朝着这个方向发射射线
RaycastHit hit;
if (Physics.Linecast(Target.position, position, out hit))
{
//Debug.Log("摄像机碰到:" + hit.collider.gameObject);
bool adjust = true;
Renderer renderer = hit.transform.GetComponent<Renderer>();
if (renderer == null) adjust = false;
if (renderer != null && !renderer.enabled) adjust = false;
if (adjust)
{
//当碰撞的不是摄像机也不是地形 那么直接移动摄像机的坐标
Vector3 posHit = hit.point;
Vector3 dir = posHit - Target.position;
//Vector3 posEnd = posHit - dir * 0.5f;
canSetPos = posHit - dir * 0.5f;
isCurHit = true;
//m_trans.position = posEnd;
//m_trans.position = position;
}
}
//摄像机与地面的检测,不要穿过地
if (canSetPos.y < Target.parent.position.y)
{
//Debug.Log("摄像机碰到了地");
canSetPos.y = Target.parent.position.y;
Vector3 relativePos = Target.position - canSetPos;
rotation = Quaternion.LookRotation(relativePos);
isCurHit = true;
}
//float oldDis = (m_trans.position - target.position).sqrMagnitude;
//float newDis = (canSetPos - target.position).sqrMagnitude;
//if ((isCurHit == false && m_isLastHit == false) || (isCurHit == true && m_isLastHit == false) || (isCurHit == true && m_isLastHit == true)) //拉进是突进
//{
// m_trans.position = canSetPos;
//}
//else if (m_isLastHit == true && isCurHit == false)
//{
// Debug.Log("镜头远离墙体");
// Vector3 mainCamPos = m_trans.position;
// Vector3 newPos = Vector3.Lerp(mainCamPos, canSetPos, getCurrentDeltaTime() * movementLerpSpeed);
// m_trans.position = newPos;
//}
m_trans.position = m_fpp ? Target.position + m_fppOffset : canSetPos;
m_trans.rotation = rotation;
}
}
}
public virtual void GodMoveCamera(Vector3 _direction,float speed)
{
if (!God) return;
_direction.y = 0;
_direction.x = Mathf.Clamp(_direction.x, -1f, 1f);
_direction.z = Mathf.Clamp(_direction.z, -1f, 1f);
// limit the input
if (_direction.magnitude > 1f)
_direction.Normalize();
Vector3 targetPosition = _rigidbody.position + _direction * speed;
Vector3 targetVelocity = (targetPosition - transform.position) / Time.deltaTime;
bool useVerticalVelocity = true;
if (useVerticalVelocity) targetVelocity.y = _rigidbody.velocity.y;
_rigidbody.velocity = targetVelocity;
}
public static float ClampAngle(float angle, float min, float max)
{
if (angle < -360F)
angle += 360F;
if (angle > 360F)
angle -= 360F;
return Mathf.Clamp(angle, min, max);
}
/// <summary>
/// 是否可以旋转
/// </summary>
/// <returns></returns>
bool IsCanRotate()
{
bool ret = false;
if (m_dicTouch.Count == 1) //只有一个手指按下并且没按在UI上
{
foreach (var item in m_dicTouch)
{
if (item.Value == false)
{
ret = true;
m_fingerId = item.Key;
}
}
}
else
{
//当有两个手指按下一个手指在UI包含在UI摇杆一个手指没在可以移动镜头
int inUI = 0;
int outUI = 0;
foreach (var item in m_dicTouch)
{
if (item.Value == true)
{
inUI++;
}
else
{
outUI++;
m_fingerId = item.Key;
}
}
if (inUI == 1 && outUI == 1)
{
ret = true;
}
}
return ret;
}
//何时才能双指控制缩放-->两个手指都没按在UI上
bool IsCanScale()
{
bool ret = true;
if (m_dicTouch.Count == 2)
{
foreach (var item in m_dicTouch)
{
if (item.Value == true)
{
ret = false;
break;
}
}
}
return ret;
}
}