在以前的仿真项目中用到了第三人称视角的移动,W、S、A、D控制角色的前后左右移动,摄像机跟随角色移动,并且摄像机做了缓冲处理。鼠标右键长按旋转控制镜头旋转,中键滑轮控制镜头拉进拉远。分为两个脚本,CharacterThirdControl挂在角色身上,CameraThirdControl挂在跟随摄像机身上。角色的标签设置为Player。跟随摄像机为主摄像机(可以根据自己需求改变)。下面直接贴代码,代码中已有注释:
1,CharacterThirdControl.cs
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(CharacterController))]
public class CharacterThirdControl: MonoBehaviour {
Transform myCamera; //跟随摄像机
private CharacterController cc;
Vector3 playerDirect; //角色的目标方向
Vector3 correctDirect; //为了矫正计算方向向量的误差
float perError = 0.2f; //误差与摄像机缓冲存在关系
float speed = 0.1f; //速度与Update的帧数有关,同样数据帧数越多,速度越快
Vector3 front; //前
Vector3 back; //后
Vector3 left; //左
Vector3 right; //右
// Use this for initialization
void Start()
{
myCamera = Camera.main.transform; //将主摄像机设置为跟随摄像机
front = Vector3.zero;
back = Vector3.zero;
left = Vector3.zero;
right = Vector3.zero;
correctDirect = Vector3.zero;
cc = transform.GetComponent<CharacterController>();
}
void LateUpdate()
{
PlayerControl();
}
/// <summary>
/// 计算方向向量函数
/// </summary>
private void CalculateDirection()
{
Vector3 temp = transform.position - myCamera.position;
temp = new Vector3(temp.x, 0, temp.z);
front = temp;
if (correctDirect!=Vector3.zero && Mathf.Abs(correctDirect.x-front.x)< perError && Mathf.Abs(correctDirect.z - front.z) < perError) //判断是否在误差范围内
{
front = correctDirect;
}
back = -front;
left =new Vector3(-front.z, 0, front.x);
right = -left;
correctDirect = front;
}
/// <summary>
/// 控制角色移动
/// </summary>
private void PlayerControl()
{
playerDirect = new Vector3(0, 0, 0);
CalculateDirection(); //计算角色的方向
if (Input.GetAxis("Horizontal") < 0) //左
{
playerDirect = left;
}
if (Input.GetAxis("Horizontal") > 0) //右
{
playerDirect = right;
}
if (Input.GetAxis("Vertical") > 0)
{
if (Input.GetAxis("Horizontal") < 0) //前左
{
playerDirect = front + left;
}
else if (Input.GetAxis("Horizontal") > 0) //前右
{
playerDirect = front + right;
}
else
{
playerDirect = front; //前
}
}
if (Input.GetAxis("Vertical") < 0)
{
if (Input.GetAxis("Horizontal") < 0) //后左
{
playerDirect = back + left;
}
else if (Input.GetAxis("Horizontal") > 0) //后右
{
playerDirect = back + right;
}
else
{
playerDirect = back; //后
}
}
if (playerDirect != Vector3.zero)
{
playerDirect += transform.position;
MoveSpeed(playerDirect);
}
}
/// <summary>
/// 调整角色方向,控制角色移动
/// </summary>
private void MoveSpeed(Vector3 direct)
{
transform.LookAt(new Vector3(direct.x, transform.position.y, direct.z));
cc.Move(transform.forward * speed);
}
}
2,CameraThirdControl.cs
using UnityEngine;
using System.Collections;
public class CameraThirdControl: MonoBehaviour
{
[Range(0, 1)]
[SerializeField]
float target_offsety = 0.6f; //高度差
[Range(0, 90)]
[SerializeField]
float initRotate = 15f; //摄像机角度
[Range(2, 10)]
[SerializeField]
float DISTANCE_DEAFULT = 3.2f; //设置摄像机与物体之间的距离
Transform target; //摄像机跟随的角色
private float distance;
private Vector3 playerTarget;
private float lastRotate;
// Use this for initialization
void Start()
{
distance = DISTANCE_DEAFULT; //设置摄像机与角色的距离
target = GameObject.FindGameObjectWithTag("Player").transform; //找到角色
playerTarget = new Vector3(target.position.x, target.position.y + target_offsety, target.position.z); //设置摄像机对着角色的位置
Quaternion cr = Quaternion.Euler(initRotate, transform.eulerAngles.y, 0); //设置摄像机与角色之间的角度
//计算摄像机的位置
Vector3 positon = playerTarget;
positon += cr * Vector3.back * distance;
transform.position = positon;
transform.rotation = target.rotation;
transform.LookAt(playerTarget);
}
// Update is called once per frame
void Update()
{
//鼠标右键控制镜头转动
if (Input.GetMouseButton(1))
{
transform.RotateAround(playerTarget, Vector3.up, Input.GetAxis("Mouse X")*3f);
}
}
//更新摄像机的位置角度等信息
void LateUpdate()
{
playerTarget = new Vector3(target.position.x, target.position.y + target_offsety, target.position.z);
Quaternion cr = Quaternion.Euler(initRotate, transform.eulerAngles.y, 0);
Vector3 positon = playerTarget + (cr * Vector3.back * distance);
RaycastHit[] hits = Physics.RaycastAll(new Ray(playerTarget, (positon - playerTarget).normalized));
distance = DISTANCE_DEAFULT;
if (hits.Length > 0)
{
RaycastHit stand = new RaycastHit();
float maxDistance = float.MaxValue;
foreach (RaycastHit hit in hits)
{
if (!hit.collider.isTrigger && hit.collider.name != target.name && hit.distance < maxDistance)
{
stand = hit;
maxDistance = stand.distance;
}
}
if (stand.collider != null)
{
string tag = stand.collider.gameObject.tag;
distance = Vector3.Distance(stand.point, playerTarget);
if (distance > DISTANCE_DEAFULT)
{
distance = DISTANCE_DEAFULT;
}
}
}
positon = playerTarget + (cr * Vector3.back * distance);
transform.position = Vector3.Lerp(transform.position, positon, 0.5f); //用于摄像机的缓冲,与误差存在关系
Debug.DrawRay(playerTarget, positon - playerTarget, Color.red);
if (lastRotate != initRotate)
{
transform.LookAt(playerTarget);
lastRotate = initRotate;
}
//鼠标中键控制镜头远近
float fov = this.GetComponent<Camera>().fieldOfView;
fov -= Input.GetAxis("Mouse ScrollWheel") * 10;
this.GetComponent<Camera>().fieldOfView = Mathf.Clamp(fov, 30, 50);
}
}
总结:以前写的最近整理了下,希望对你有帮助! 2018\4\16