游戏中的摄像机,都是聚焦到客户端主角身上。
为了实现这个功能,我写了两个脚本,第一个脚本用来控制客户端主角的位置和旋转,使用WSAD键控制主角的前后左右移动,使用鼠标右键控制主角的旋转。
第二个脚本是根据客户端主角的transform,设置摄像机的transform,使得摄像机聚焦在主角身上。
这两个脚本都是设置成客户端主角的组件。
第一个脚本 FiMainPlayerMoveCtrl.cs
//-----------------------------------------------------------------
//1,客户端主角的移动控制,使用WSAD键控制上下左右移动,使用鼠标右键控制旋转。
//2,左手坐标系。
//3,欧拉角使用的单位是角度,不是弧度。
//-----------------------------------------------------------------
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-----------------------------------------------------------------
public class FiMainPlayerMoveCtrl : MonoBehaviour
{
public float moveSpeed = 30.0f;
public float rotateSpeed = 0.2f;
public float mouseWheelSpeed = 50.0f;
public static Vector3 kUpDirection = new Vector3(0.0f, 1.0f, 0.0f);
//记录角色的旋转角度。
//以上方向为轴的旋转角度。
private float m_fEulerAngleUpDir = 0.0f;
//以右方向为轴的旋转角度。
//这个欧拉角不会施加在角色身上,当摄像机聚焦在本角色上时,会施加到摄像机上。
private float m_fEulerAngleRightDir = 0.0f;
//当摄像机聚焦在本角色上时,记录本角色与摄像机之间的直线距离。
private float m_fDistanceFromCamera = 100.0f;
//控制角色旋转的成员变量。
private float m_fLastMousePosX = 0.0f;
private float m_fLastMousePosY = 0.0f;
private bool m_bMouseRightKeyDown = false;
//记录本帧内Transform是否发生了变化。
//当摄像机聚焦在本角色上时,只有本Transform发生了变化,才更新摄像机的Transform。
private bool m_bTransformChanged = false;
//-----------------------------------------------------------------
void Start()
{
Vector3 kEulerAngles = transform.eulerAngles;
m_fEulerAngleRightDir = kEulerAngles.x;
m_fEulerAngleUpDir = kEulerAngles.y;
}
//-----------------------------------------------------------------
void Update()
{
m_bTransformChanged = false;
//判断旋转
if (Input.GetMouseButtonDown(1)) //鼠标右键刚刚按下了
{
if (m_bMouseRightKeyDown == false)
{
m_bMouseRightKeyDown = true;
Vector3 kMousePos = Input.mousePosition;
m_fLastMousePosX = kMousePos.x;
m_fLastMousePosY = kMousePos.y;
}
}
else if (Input.GetMouseButtonUp(1)) //鼠标右键刚刚抬起了
{
if (m_bMouseRightKeyDown == true)
{
m_bMouseRightKeyDown = false;
m_fLastMousePosX = 0;
m_fLastMousePosY = 0;
}
}
else if (Input.GetMouseButton(1)) //鼠标右键处于按下状态中
{
if (m_bMouseRightKeyDown)
{
Vector3 kMousePos = Input.mousePosition;
float fDeltaX = kMousePos.x - m_fLastMousePosX;
float fDeltaY = kMousePos.y - m_fLastMousePosY;
m_fLastMousePosX = kMousePos.x;
m_fLastMousePosY = kMousePos.y;
m_fEulerAngleRightDir -= (fDeltaY * rotateSpeed);
m_fEulerAngleUpDir -= -(fDeltaX * rotateSpeed);
Vector3 kNewEuler = new Vector3(0.0f, m_fEulerAngleUpDir, 0.0f);
transform.eulerAngles = kNewEuler;
m_bTransformChanged = true;
}
}
//判断位移
float fMoveDeltaX = 0.0f;
float fMoveDeltaZ = 0.0f;
float fDeltaTime = Time.deltaTime;
if (Input.GetKey(KeyCode.A))
{
fMoveDeltaX -= moveSpeed * fDeltaTime;
}
if (Input.GetKey(KeyCode.D))
{
fMoveDeltaX += moveSpeed * fDeltaTime;
}
if (Input.GetKey(KeyCode.W))
{
fMoveDeltaZ += moveSpeed * fDeltaTime;
}
if (Input.GetKey(KeyCode.S))
{
fMoveDeltaZ -= moveSpeed * fDeltaTime;
}
if (fMoveDeltaX != 0.0f || fMoveDeltaZ != 0.0f)
{
Vector3 kForward = transform.forward;
Vector3 kRight = Vector3.Cross(kUpDirection, kForward);
Vector3 kNewPos = transform.position;
kNewPos += kRight * fMoveDeltaX;
kNewPos += kForward * fMoveDeltaZ;
//把Y值设置成0,只能在平面上移动。
kNewPos.y = 0.0f;
transform.position = kNewPos;
m_bTransformChanged = true;
}
float fWheel = Input.GetAxis("Mouse ScrollWheel");
if (fWheel != 0.0f)
{
m_fDistanceFromCamera -= fWheel * mouseWheelSpeed;
m_bTransformChanged = true;
}
}
//-----------------------------------------------------------------
public float GetEulerAngleRightDir()
{
return m_fEulerAngleRightDir;
}
//-----------------------------------------------------------------
public float GetEulerAngleUpDir()
{
return m_fEulerAngleUpDir;
}
//-----------------------------------------------------------------
public float GetDistanceFromCamera()
{
return m_fDistanceFromCamera;
}
//-----------------------------------------------------------------
public bool IsTransformChanged()
{
return m_bTransformChanged;
}
}
//-----------------------------------------------------------------
第二个脚本 FiCameraControl.cs
//-----------------------------------------------------------------
//1,摄像机要聚焦在GameObjectA上,那么就把本脚本作为一个组件,添加到GameObjectA中。
//2,GameObjectA中必须包含 FiMainPlayerMoveCtrl 组件。
//3,左手坐标系。
//-----------------------------------------------------------------
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-----------------------------------------------------------------
public class FiCameraControl : MonoBehaviour
{
//本Object必须有一个 FiMainPlayerMoveCtrl 组件。
private FiMainPlayerMoveCtrl m_kMainPlayerMoveCtrl = null;
//摄像机的 Transform 组件。
private Transform m_kMainCameraTransform = null;
//记录是否为第一帧。
//如果是第一帧,必须更新摄像机的Transform,使得摄像机聚焦在本Object上。
private bool m_bFirstFrame = true;
//-----------------------------------------------------------------
void Start()
{
m_kMainPlayerMoveCtrl = GetComponent<FiMainPlayerMoveCtrl>();
m_kMainCameraTransform = Camera.main.transform;
m_bFirstFrame = true;
}
//-----------------------------------------------------------------
void Update()
{
}
//-----------------------------------------------------------------
void LateUpdate()
{
if (m_kMainPlayerMoveCtrl == null)
{
return;
}
if (m_kMainPlayerMoveCtrl.IsTransformChanged() == false)
{
if (m_bFirstFrame == false)
{
return;
}
}
m_bFirstFrame = false;
//设置摄像机的旋转。
float fEulerAngleRightDir = m_kMainPlayerMoveCtrl.GetEulerAngleRightDir();
float fEulerAngleUpDir = m_kMainPlayerMoveCtrl.GetEulerAngleUpDir();
Vector3 kEulerAngle = new Vector3(fEulerAngleRightDir, fEulerAngleUpDir, 0.0f);
m_kMainCameraTransform.eulerAngles = kEulerAngle;
//设置摄像机的位置。
Vector3 kPos = transform.position;
float fDistance = m_kMainPlayerMoveCtrl.GetDistanceFromCamera();
kPos -= m_kMainCameraTransform.forward * fDistance;
m_kMainCameraTransform.position = kPos;
}
}
//-----------------------------------------------------------------