曾几何时一直痴迷着手游,特别是3D的游戏,继而在学过游戏开发之后对其中的技术实现也是充满了好奇。今天带来的就是对游戏角色的至关重要的相机系统的基础实现,当然基于目前技术水平所限制,我分享的其实也不是很难的东西哈。
相机系统的大概了解
所谓的相机系统其实也就是对相机的管理,想想当初玩游戏通过屏幕手势对游戏角色的各方面观察,这也就是我们普遍意义上的相机系统,当然这算是比较简单的一种,我们所要实现的就是通过屏幕终端手势来控制游戏中的相机。
效果图
有童鞋可能不明白我在屏幕上干了啥,这里说明下,其实也就是上下左右滑动和鼠标滚轮滚动而已,然后实现的结果就是图中所示。
实现原理概括
其实从效果图中就能看出,我所做的操作无非手势的不同,所对应的就是相机的状态改变,换作代码逻辑也很好分析。
首先我需要有监听屏幕上下左右滑动的事件,鼠标滚轮的触发事件,事件有了之后就需要对相机进行控制,相机的控制类型无非旋转和位移两种。(上下左右滑动对应相机的旋转,位移对应着鼠标滚轮滚动)做完这些其实也就剩不了什么了,这里需要提的一点是,相机结构的构造比较重要,仅仅只依靠一个相机我感觉不好操作,所以这里提供了一个相机结构参考,如下图
相机结构介绍完了,那么整体的相机系统的原理也差不多了,接下来可以看看代码实现。
关键代码演示
首先可以看下整个系统的事件监听,这里导入了手势插件FingerGestures
public class FingerEvent : MonoBehaviour
{
public static FingerEvent Instance;
public enum FingerDir
{
Up,
Down,
Left,
Right
}
/// <summary>
/// 滑动委托
/// </summary>
public Action<FingerDir> OnFingerDrag;
public enum ZoomType
{
In,
Out
}
/// <summary>
/// 缩放的委托
/// </summary>
public Action<ZoomType> OnZoom;
private Vector2 m_TempFinger1Pos;
private Vector2 m_TempFinger2Pos;
private Vector2 m_OldFinger1Pos;
private Vector2 m_OldFinger2Pos;
/// <summary>
/// 玩家点击地面的委托
/// </summary>
public Action OnPlayerClickGround;
/// <summary>
/// 拖动的旧位置
/// </summary>
private Vector2 m_OldDragPos;
/// <summary>
/// 拖动的方向
/// </summary>
private Vector2 m_DragDir;
/// <summary>
/// 交互参数
/// </summary>
private int m_PreFinger = -1;
void Awake()
{
Instance = this;
}
void OnEnable()
{
//启动时调用,这里开始注册手势操作的事件。
//按下事件: OnFingerDown就是按下事件监听的方法,这个名子可以由你来自定义。方法只能在本类中监听。下面所有的事件都一样!!!
FingerGestures.OnFingerDown += OnFingerDown;
//开始拖动事件
FingerGestures.OnFingerDragBegin += OnFingerDragBegin;
//拖动中事件...
FingerGestures.OnFingerDragMove += OnFingerDragMove;
//拖动结束事件
FingerGestures.OnFingerDragEnd += OnFingerDragEnd;
}
private void Update()
{
if (Input.GetAxis("Mouse ScrollWheel") < 0)
{
if (OnZoom != null)
{
OnZoom(ZoomType.Out);
}
}
else if (Input.GetAxis("Mouse ScrollWheel") > 0)
{
if (OnZoom != null)
{
OnZoom(ZoomType.In);
}
}
}
void OnDisable()
{
//关闭时调用,这里销毁手势操作的事件
//和上面一样
FingerGestures.OnFingerDown -= OnFingerDown;
FingerGestures.OnFingerDragBegin -= OnFingerDragBegin;
FingerGestures.OnFingerDragMove -= OnFingerDragMove;
FingerGestures.OnFingerDragEnd -= OnFingerDragEnd;
}
//按下时调用
void OnFingerDown(int fingerIndex, Vector2 fingerPos)
{
m_PreFinger = 1;
}
//开始滑动
void OnFingerDragBegin(int fingerIndex, Vector2 fingerPos, Vector2 startPos)
{
m_PreFinger = 2;
m_OldDragPos = fingerPos;
}
//滑动结束
void OnFingerDragEnd(int fingerIndex, Vector2 fingerPos)
{
m_PreFinger = 4;
}
//滑动中
void OnFingerDragMove(int fingerIndex, Vector2 fingerPos, Vector2 delta)
{
m_PreFinger = 3;
m_DragDir = fingerPos - m_OldDragPos;
if (m_DragDir.y < m_DragDir.x && m_DragDir.y > -m_DragDir.x)
{
//向右
if (OnFingerDrag != null)
{
OnFingerDrag(FingerDir.Right);
}
}
else if (m_DragDir.y > m_DragDir.x && m_DragDir.y < -m_DragDir.x)
{
//向左
if (OnFingerDrag != null)
{
OnFingerDrag(FingerDir.Left);
}
}
else if (m_DragDir.y > m_DragDir.x && m_DragDir.y > -m_DragDir.x)
{
//向上
if (OnFingerDrag != null)
{
OnFingerDrag(FingerDir.Up);
}
}
else
{
//向下
if (OnFingerDrag != null)
{
OnFingerDrag(FingerDir.Down);
}
}
}
}
然后就是我们的相机控制逻辑了,其实也就是针对我们之前的相机结构来的,运用的也就是transform里头的东西
public class CameraCtr : MonoBehaviour {
public static CameraCtr Instance;
/// <summary>
/// 控制摄像机上下
/// </summary>
[SerializeField]
private Transform m_CameraUpAndDown;
/// <summary>
/// 控制摄像机缩放父物体
/// </summary>
[SerializeField]
private Transform m_CameraZoomContainer;
/// <summary>
/// 摄像机容器
/// </summary>
[SerializeField]
private Transform m_CameraContainer;
void Awake()
{
Instance = this;
}
/// <summary>
/// 初始化
/// </summary>
public void Init()
{
m_CameraUpAndDown.localEulerAngles = new Vector3(0, 0, Mathf.Clamp(m_CameraUpAndDown.localEulerAngles.z, 10f, 80f));
}
/// <summary>
/// 设置摄像机旋转
/// </summary>
/// <param name="type">0=左 1=右</param>
public void SetCameraRotate(int type)
{
transform.Rotate(0,80*Time.deltaTime * (type == 1?-1:1),0);
}
/// <summary>
/// 设置摄像机上下
/// </summary>
/// <param name="type">0=上 1=下</param>
public void SetCameraUpAndDown(int type)
{
m_CameraUpAndDown.Rotate(0,0, 30 * Time.deltaTime * (type == 1 ? -1 : 1));
m_CameraUpAndDown.localEulerAngles = new Vector3(0,0,Mathf.Clamp(m_CameraUpAndDown.localEulerAngles.z,10f,80f));
}
/// <summary>
/// 设置摄像机缩放
/// </summary>
/// <param name="type">0=拉近 1=拉远</param>
public void SetCameraZoom(int type)
{
m_CameraContainer.Translate(Vector3.forward * 20 * Time.deltaTime * (type == 1 ? -1 : 1));
m_CameraContainer.localPosition = new Vector3(0, 0, Mathf.Clamp(m_CameraContainer.localPosition.z, -5f, 8f));
}
public void AutoLookAt(Vector3 pos)
{
m_CameraZoomContainer.LookAt(pos);
}
}
然后就没有然后了,代码中有注释,看不懂可以多看几遍哈!
代码地址
具体代码我已经上传Github,看这里
代码上可能还存在些问题,欢迎提出自己的意见。
总结
以前其实对相机系统不是很了解,而这篇分享也是基于目前我所学习的课程的笔记而已,也希望后面能更多得学习新的东西能拿出来分享。