# unity 角色第三视角移动

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

}