在游戏中,最常见的视角控制就是鼠标上下左右移动来实现相机的上下左右移动,以及鼠标滚轮的滚动来实现视角的缩放
下面将介绍这三种功能的实现:
因为场景是一个三维坐标系,所以需要的地方很多,这里引入几个变量,distance, roll, rot , distance ,d为相机和主角之间的空间距离,roll为竖截面distance和x-o-y平面的夹角,d为distance在x-o-y平面的投影,即d = distance * cos(roll),rot为投影d的旋转角度(弧度)计算相机位置的代码如下:
//计算相机的地面投影和相机高度
float d = distance * Mathf.Cos(roll);
float height = distance * Mathf.Sin(roll);
Vector3 cameraPos;
//计算相机的坐标
cameraPos.x = target.transform.position.x + d * Mathf.Cos(rot);
cameraPos.z = target.transform.position.z + d * Mathf.Sin(rot);
cameraPos.y = target.transform.position.y + height;
最后相机要始终朝向主角:
Camera.main.transform.position = cameraPos;
Camera.main.transform.LookAt(target.transform.position);
上述代码即可实现镜头的跟随,接下来就是要实现鼠标的调整视角,其实只需要通过获取轴的操作来使rot(水平转向) 、roll(垂直转向)、distance(缩放距离)做改变
即 Input.GetAxis("Mouse X") 、Input.GetAxis("Mouse Y") 、Input.GetAxis("Mouse ScrollWheel") 来改变上面三个值
完整代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraCtrl : MonoBehaviour {
//目标物体
private GameObject target;
//相机与目标物体的距离
public float distance;
//横向角度
public float rotDegree = 0;
public float rotSpeed = 0.2f;
float rot; //弧度
//纵向角度
public float rollDegree = 30;
public float rollSpeed = 0.2f;
public float minRollDegree = 0;
public float maxRollDegree = 70;
float roll; //弧度
//摄像机移动速度(滚轮控制)
public float zoomSpeed = 1.5f;
public float minDis = 8;
public float maxDis = 22;
// Use this for initialization
void Start () {
target = GameObject.Find("tank");
GetTarget(target);
}
// Update is called once per frame
void Update () {
Rotate();
Roll();
Zoom();
//角度转换成弧度
rot = rotDegree * Mathf.PI / 180;
roll = rollDegree * Mathf.PI / 180;
//计算相机的地面投影和相机高度
float d = distance * Mathf.Cos(roll);
float height = distance * Mathf.Sin(roll);
Vector3 cameraPos;
//计算相机的坐标
cameraPos.x = target.transform.position.x + d * Mathf.Cos(rot);
cameraPos.z = target.transform.position.z + d * Mathf.Sin(rot);
cameraPos.y = target.transform.position.y + height;
Camera.main.transform.position = cameraPos;
Camera.main.transform.LookAt(target.transform.position);
}
//鼠标水平滑动调整视角
void Rotate() {
float value = Input.GetAxis("Mouse X");
rotDegree -= value * rotSpeed;
}
//鼠标垂直方向调整视角
void Roll() {
float value = Input.GetAxis("Mouse Y");
rollDegree += value * rollSpeed;
rollDegree = Mathf.Clamp(rollDegree, minRollDegree, maxRollDegree);
}
//滚轮调整视角的远近
void Zoom() {
float value = Input.GetAxis("Mouse ScrollWheel");
distance -= value * zoomSpeed;
distance = Mathf.Clamp(distance, minDis, maxDis);
}
//让相机始终跟随目标物体身上的某一点
void GetTarget(GameObject target) {
if (target.transform.Find("cameraPoint") != null)
{
this.target = target.transform.Find("cameraPoint").gameObject;
}
else {
return;
}
}
}
除此之外,再介绍一种新方法,主要针对第一人称视角,代码如下:
using UnityEngine;
using System.Collections;
[AddComponentMenu("Game/Player")]
public class Player : MonoBehaviour
{
public Transform m_transform;
//角色控制器
CharacterController m_ch;
// 移动速度
float m_movSpeed = 6.0f;
// 重力
float m_gravity = 2.0f;
// 相机组件
Transform m_camTransform;
// �������ת�Ƕ�
Vector3 m_camRot;
// ������߶�
float m_camHeight = 1.4f;
// ����ֵ
public int m_life = 20;
//ǹ��transform
Transform m_muzzlepoint;
// ���ʱ���������䵽����ײ��
public LayerMask m_layer;
// ����Ŀ��������Ч��
public Transform m_fx;
// �����Ч
public AudioClip m_audio;
// ������ʱ���ʱ��
float m_shootTimer = 0;
public float slide = 5;
private AudioSource audioSource;
private Animation anim;
private Transform akTrans;
public GameObject[] guns;
public Transform currentGun;
// Use this for initialization
void Start()
{
m_transform = this.transform;
// 得到Player身上的CharacterController组件
m_ch = this.GetComponent<CharacterController>();
// 主相机
m_camTransform = GameObject.Find("Main Camera").transform;
// �����������ʼλ��
Vector3 pos = m_transform.position;
pos.y += m_camHeight;
m_camTransform.position = pos;
// �������������ת����������һ��
m_camTransform.rotation = m_transform.rotation;
m_camRot = m_camTransform.eulerAngles;
Screen.lockCursor = true;
// ����muzzlepoint
m_muzzlepoint = m_camTransform.Find("M16/weapon/muzzlepoint").transform;
currentGun = guns[0].transform;
anim = currentGun.GetComponent<Animation>();
audioSource = GetComponent<AudioSource>();
}
// Update is called once per frame
void Update()
{
// �������Ϊ0��ʲôҲ����
if (m_life <= 0)
return;
Control();
Move();
ChangeGun();
}
//相机、射击控制
void Control()
{
//��ȡ����ƶ�����
float rh = Input.GetAxis("Mouse X");
float rv = Input.GetAxis("Mouse Y");
// ��ת�����
if (Input.GetMouseButton(1))
{
m_camRot.x -= rv * slide;
m_camRot.y += rh * slide;
m_camTransform.eulerAngles = m_camRot;
// ʹ���ǵ��������������һ��
Vector3 camrot = m_camTransform.eulerAngles;
camrot.x = 0; camrot.z = 0;
m_transform.eulerAngles = camrot;
}
// ����������ʱ��
m_shootTimer -= Time.deltaTime;
//射击操作:按下鼠标左键,并且CD等于0 (GetMouseButton参数0代表左键,1代表右键)
if (Input.GetMouseButton(0) && m_shootTimer <= 0)
{
m_shootTimer = 0.1f;
ShootAnim();
//audioSource.PlayOneShot(audioSource.clip);
audioSource.PlayScheduled(0.01f);
//this.audio.PlayOneShot(m_audio);
// ���ٵ�ҩ�����µ�ҩUI
GameManager.Instance.SetAmmo(1);
// RaycastHit�����������ߵ�̽����
RaycastHit info;
// ��muzzlepoint��λ�ã����������������������һ������
// ����ֻ����m_layer��ָ���IJ���ײ
bool hit = Physics.Raycast(m_muzzlepoint.position, m_camTransform.TransformDirection(Vector3.forward), out info, 100, m_layer);
if (hit)
{
// ���������tagΪenemy����Ϸ��
if (info.transform.tag.CompareTo("enemy") == 0)
{
Enemy enemy = info.transform.GetComponent<Enemy>();
// ���˼�������
enemy.OnDamage(1);
}
// �����еĵط��ͷ�һ������Ч��
Instantiate(m_fx, info.point, info.transform.rotation);
}
}
// ʹ�������λ��������һ��
Vector3 pos = m_transform.position;
pos.y += m_camHeight;
m_camTransform.position = pos;
}
//移动控制
void Move()
{
// ����3��ֵ�����ƶ�
float xm = 0, ym = 0, zm = 0;
// �����˶�
ym -= m_gravity * Time.deltaTime;
// ���������˶�
if (Input.GetKey(KeyCode.W))
{
zm += m_movSpeed * Time.deltaTime;
}
else if (Input.GetKey(KeyCode.S))
{
zm -= m_movSpeed * Time.deltaTime;
}
if (Input.GetKey(KeyCode.A))
{
xm -= m_movSpeed * Time.deltaTime;
}
else if (Input.GetKey(KeyCode.D))
{
xm += m_movSpeed * Time.deltaTime;
}
// ʹ�ý�ɫ�������ṩ��Move���������ƶ� �����Զ������ײ
m_ch.Move(m_transform.TransformDirection(new Vector3(xm, ym, zm)));
}
//射击动画
void ShootAnim() {
anim.Play("Single_Shot");
}
//切换枪
int index = 0;
private void ChangeGun() {
if (Input.GetAxis("Mouse ScrollWheel") < 0)
{
currentGun.gameObject.SetActive(false);
index--;
if (index < 0) {
index = guns.Length - 1;
}
currentGun = guns[index].transform;
currentGun.gameObject.SetActive(true);
anim = currentGun.GetComponent<Animation>();
GunAudio(currentGun.gameObject.name);
}
if (Input.GetAxis("Mouse ScrollWheel") > 0) {
currentGun.gameObject.SetActive(false);
index++;
if (index > guns.Length - 1) {
index = 0;
}
currentGun = guns[index].transform;
currentGun.gameObject.SetActive(true);
anim = currentGun.GetComponent<Animation>();
GunAudio(currentGun.gameObject.name);
}
}
//枪声
private void GunAudio(string audio) {
AudioClip currentClip = Resources.Load<AudioClip>("Sound/"+audio) as AudioClip;
Debug.Log("Clip:" + currentClip);
audioSource.clip = currentClip;
}
void OnDrawGizmos()
{
Gizmos.DrawIcon(this.transform.position, "Spawn.tif");
}
// �˺�
public void OnDamage(int damage)
{
m_life -= damage;
// ����UI
GameManager.Instance.SetLife(m_life);
// �������Ϊ0�����������ʾ
if (m_life <= 0)
Screen.lockCursor = false;
}
}