using System;
using UnityEngine;
/// <summary>
/// 方便其他地方找到2d摄像机 和NGUI的root
/// 本脚本挂在NGUI创建的 UI Root物体上
/// </summary>
public class NGUIRoot : UnitySingleton<NGUIRoot>
{
public Camera Camera2d; //手动面板赋值
public Camera Camera3d; //手动面板赋值
//5个NGUI的锚点 UIAnchor.cs
[HideInInspector]
public Transform leftDir;
[HideInInspector]
public Transform rightDir;
[HideInInspector]
public Transform topDir;
[HideInInspector]
public Transform downDir;
[HideInInspector]
public Transform centerDir;
[HideInInspector]
public GameObject rootObj;
void Awake()
{
if (Camera3d == null || Camera2d == null)
{
Debug.LogError("worldcamera == null || uiCamera == null 清手动面板赋值");
}
DontDestroyOnLoad(gameObject);
DontDestroyOnLoad(Camera3d.gameObject);
rootObj = gameObject;
Creat5Anchor();
}
//代码创建5个5个NGUI的锚点 UIAnchor.cs
void Creat5Anchor()
{
CreatAnchor("leftDir", UIAnchor.Side.Left, ref leftDir);
CreatAnchor("rightDir", UIAnchor.Side.Right, ref rightDir);
CreatAnchor("topDir", UIAnchor.Side.Top, ref topDir);
CreatAnchor("downDir", UIAnchor.Side.Bottom, ref downDir);
CreatAnchor("centerDir", UIAnchor.Side.Center, ref centerDir);
}
void CreatAnchor(string name, UIAnchor.Side side, ref Transform t)
{
GameObject go = null;
UIAnchor ua = null;
go = new GameObject(name);
ua = go.AddComponent<UIAnchor>();
ua.side = side;
ua.uiCamera = Camera2d;
ua.runOnlyOnce = false;
go.transform.SetParent(rootObj.transform);
t = go.transform;
}
/// <summary>
/// 在3d世界中获取相对于屏幕的上下左右方向
/// </summary>
/// <param name="dir"></param>
/// <returns></returns>
public Vector3 GetSreenDir(Dir dir)
{
Vector3 dirPos = Vector3.zero;
Vector3 centerPos = Vector3.zero;
switch (dir)
{
case Dir.f:
dirPos = NguiToWorld(topDir.position);
break;
case Dir.d:
dirPos = NguiToWorld( downDir.position);
break;
case Dir.l:
dirPos = NguiToWorld(leftDir.position);
break;
case Dir.r:
dirPos = NguiToWorld(rightDir.position);
break;
}
centerPos = NguiToWorld(centerDir.position);
return (dirPos - centerPos).normalized;
}
/// <summary>
/// NGUI 坐标转世界坐标
/// </summary>
/// <param name="worldcamera"></param>
/// <param name="uiCamera"></param>
/// <param name="uiPos"></param>
/// <returns></returns>
public static Vector3 NguiToWorld(Vector3 uiPos)
{
Vector3 pos = _2dCamera.WorldToScreenPoint(uiPos); //NGUI坐标转屏幕坐标
pos.z = 1f;//设置为零时转换后的pos全为0,屏幕空间的原因,被坑过的我提醒大家,切记要改!
pos = _3dCamera.ScreenToWorldPoint(pos); //屏幕坐标转NGUI坐标
pos.y = 0f;
return pos;
}
public static Camera _3dCamera
{
get
{
return NGUIRoot.Instance.Camera3d;
}
}
public static Camera _2dCamera
{
get
{
return NGUIRoot.Instance.Camera2d;
}
}
}
//方向
public enum Dir
{
f,
d,
l,
r,
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
/// <summary>
/// 摄像机移动脚本,有两种移动方式,A跟随角色移动,B鼠标超过屏幕边缘移动,就是鼠标在屏幕上方时,摄像机向前移动
/// 默认摄像机是MainCamera,角色是"Player"标签查找
/// 本脚本随便挂在一个场景中的物体上
/// </summary>
public class CameraFollowPlayer : MonoBehaviour
{
Camera camera;//场景相机
GameObject player;//玩家角色
/// <summary>
/// 摄像机相对角色的拉远拉近缩放速度.
/// </summary>
public float forwardAndBackZoomSpeed = 13f;
/// <summary>
/// 摄像机与角色最大最小距离
/// </summary>
public float withPlayerDistanceMin = 3.9f;
public float withPlayerDistanceMax = 37f;
//跟随平滑速度
public float SmoothSpeed = 1.7f;
public float CameramoveSpeed = 7f;
//摄像机移动方式
public enum CameraMoveType
{
FollowPlayerMove,//跟随角色移动
MouseExceedScreenFrameMove,//鼠标超过屏幕边缘移动
}
public CameraMoveType cameraMoveType = CameraMoveType.MouseExceedScreenFrameMove;
public bool GetCamera()
{
if (!camera)
{
camera = Camera.main;
}
return camera != null ? true : false;
}
public bool GetPlayer()
{
if (!player)
{
player = GameObject.FindWithTag("Player");
}
return player != null ? true : false;
}
public Transform cameraT
{
get
{
if (GetCamera() == false)
{
Debug.LogError("no Camera");
return null;
}
return camera.transform;
}
}
public Vector3 cameraPos
{
get
{
return cameraT.position;
}
}
public Transform PlayerT
{
get
{
if (GetPlayer() == false)
{
Debug.LogError("no Player");
return null;
}
return player.transform;
}
}
public Vector3 PlayerPos
{
get
{
return PlayerT.position;
}
}
/// <summary>
/// cameraPos -PlayerPos的摄像机减角色的偏移值.
/// </summary>
Vector3 offset;
Quaternion cameraOriginalRotation;//相机初始旋转.
Quaternion cameraCurrentRotation;//相机当前旋转.
Vector3 OriginalForwardPoint;
// Use this for initialization
void Start()
{
StartGameTimeCameraMoveToFollowPlayer();
offset = cameraPos - PlayerPos;
}
// Update is called once per frame
void Update()
{
ScrollView();
if (cameraMoveType == CameraMoveType.MouseExceedScreenFrameMove)
{
MouseExceedScreenFrameMove();
isMouseExceed = true;
RotationView(cameraT, PlayerT, ref offset, 3f, 3f, 0.5f);
}
}
private bool isMouseExceed = false;
private bool isFollwInit = false;
void FixedUpdate()
{
if (cameraMoveType == CameraMoveType.FollowPlayerMove)
{
//第一种情况,切换过来
if (isMouseExceed)
{
StartGameTimeCameraMoveToFollowPlayer();
isMouseExceed = false;
}
else//第二种一开始就是跟随模式
{
if (!isFollwInit)
{
isFollwInit = true;
StartGameTimeCameraMoveToFollowPlayer();
}
}
FollowPlayer();
}
}
/// <summary>
/// 跟随角色
/// </summary>
void FollowPlayer()
{
Vector3 targetPos = PlayerT.position + offset;
//误差大于0.1f 才移动
if (Vector3.Distance(cameraPos, targetPos)> 0.1f)
{
cameraT.position = Vector3.Lerp(cameraPos, targetPos, SmoothSpeed * Time.deltaTime);
}
}
private bool isFollow = false;
/// <summary>
/// 开始游戏时,摄像机对准角色初始位置
/// </summary>
void StartGameTimeCameraMoveToFollowPlayer()
{
cameraOriginalRotation = Quaternion.Euler(62f, -114f, -7f);
cameraT.rotation = cameraOriginalRotation;
cameraT.position = new Vector3(PlayerT.position.x + 3f, PlayerT.position.y + 9f, PlayerT.position.z + 1f);
}
/// <summary>
/// 鼠标滚轮拉近拉运摄像机.
/// </summary>
void ScrollView()
{
if (Input.GetAxis("Mouse ScrollWheel") != 0)
{
float distance = Vector3.Distance(cameraPos, PlayerPos);// 摄像机与角色的距离;
distance += Input.GetAxis("Mouse ScrollWheel") * forwardAndBackZoomSpeed;
distance = Mathf.Clamp(distance, withPlayerDistanceMin, withPlayerDistanceMax);//限制缩减的最小最大距离
offset = offset.normalized * distance; //更新摄像机与角色位置偏移,使摄像机与角色位置偏移除去距离变成方向的向量 在乘以距离就是要偏移的位置.
cameraT.position = PlayerT.position + offset;
}
}
float timer;
bool startRotate;
/// <summary>
///鼠标右键按下, 实现摄像机对角色左右上下旋转.time =按下右键多长才旋转.
/// </summary>
void RotationView(Transform cameraT, Transform playerT, ref Vector3 offset, float LeftRMoveSpeed, float UpDMoveSpeed, float time)
{
if (Input.GetMouseButtonDown(1))
{
//Debug.Log ( "鼠标右键瞬间按下=" + Time.realtimeSinceStartup );
timer = Time.realtimeSinceStartup;
startRotate = false;
}
if (!Input.GetMouseButton(1))
{
//Debug.Log ( "鼠标右键弹起=" + Time.realtimeSinceStartup );
return;
}
if (Input.GetMouseButton(1))
{
// Debug.Log ( "鼠标右键按下中=" + Time.realtimeSinceStartup + "))result=" +( timer + time <= Time.realtimeSinceStartup?"true":"false ") );
if (timer + time <= Time.realtimeSinceStartup)
{
startRotate = true;
}
}
if (startRotate)
{
float RotateThreshold = 0.1f;//旋转阀值,超过才旋转
//旋转前让摄像机与角色对齐
//让摄像机rotation.z归0
//摄像机.position.x== 角色.position.x
//transform.RotateAround旋转会修改position和rotation
//======开始旋转===
//===左右旋转=====
if (Input.GetAxis("Mouse X") > RotateThreshold || Input.GetAxis("Mouse X") < -RotateThreshold)
{
// Debug.Log ( Input.GetAxis ( "Mouse X" ) );
//transform.RotateAround(角色位置,角色.transform.up,rotateSpeed *Input.GetAxis ("Mouse X") );//绕角色位置这个点,绕Y轴旋转. 注意:旋转的时候不能一直在修改相机的位置,造成旋转错误.
cameraT.RotateAround(playerT.position, playerT.up, LeftRMoveSpeed * Input.GetAxis("Mouse X"));//绕角色位置这个点,绕Y轴旋转. 注意:旋转的时候不能一直在修改相机的位置,造成旋转错误.
offset = cameraT.position - playerT.position;//旋转后摄像机位置改变,更新摄像机与角色位置偏移
}
//===左右旋转=====
//===上下旋转====
//旋转前记录一下摄像机的旋转和位置.如果旋转超过限定的边界,就恢复.就是让旋转无效
//旋转会修改position和rotation
if (Input.GetAxis("Mouse Y") > RotateThreshold || Input.GetAxis("Mouse Y") < -RotateThreshold)
{
Vector3 originalPos = cameraT.position;
Quaternion originalRotation = cameraT.rotation;
//transform.RotateAround(角色位置,摄像机.transform.right,-rotateSpeed *Input.GetAxis ("Mouse Y") );//绕角色位置这个点,绕Y轴旋转. 注意:旋转的时候不能一直在修改相机的位置,造成旋转错误.
cameraT.RotateAround(playerT.position, cameraT.right, -UpDMoveSpeed * Input.GetAxis("Mouse Y"));//绕角色位置这个点,绕Y轴旋转. 注意:旋转的时候不能一直在修改相机的位置,造成旋转错误.
//如果旋转超出范围,将属性归为未旋转前的值,就是让旋转无效
float x = cameraT.eulerAngles.x;
if (x < 10 || x > 80)
{
cameraT.position = originalPos;
cameraT.rotation = originalRotation;
}
offset = cameraT.position - playerT.position;//旋转后摄像机位置改变,更新摄像机与角色位置偏移
//===上下旋转====
}
cameraOriginalRotation = cameraT.rotation;
}
}
/// <summary>
/// 鼠标超过屏幕移动
/// </summary>
void MouseExceedScreenFrameMove()
{
if (Input.mousePosition.y >= Screen.height)//forward
{
updateCameraPos(Dir.f);
}
if (Input.mousePosition.y <= 0)//back
{
updateCameraPos(Dir.d);
}
if (Input.mousePosition.x >= Screen.width)
{
updateCameraPos(Dir.r);
}
if (Input.mousePosition.x <= 0)//right
{
updateCameraPos(Dir.l);
}
}
void updateCameraPos(Dir d)
{
Vector3 dir = NGUIRoot.Instance.GetSreenDir(d);
Vector3 pos = cameraPos + dir * CameramoveSpeed * Time.deltaTime;
cameraT.position = pos;
//Debug.LogError("Dir == "+ d);
}
}