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); } }