知识点记录(希望是以后要用到了是可以直接拿来复制粘贴)
第三人称角色控制器
PC端版本
标准功能:按下WASD移动,空格键跳跃,Shift加速,鼠标右键控制摄像机旋转视角
角色移动部分代码
public float walkSpeed = 5;//移动
public float runSpeed = 10;//奔跑
public float turnSmoothTime = 0.13f;//角色转向平滑时间
float turnSmoothVelocity;
public Camera cameraT;
private Rigidbody rb;
public Animator ani;//动画控制器,没有的可以不加,在下面脚本里删掉就行
private void Awake()
{
rb = transform.GetComponent<Rigidbody>();
cameraT = Camera.main;
}
void FixedUpdate()
{
PlayerMoveThirdPerson();
}
//主要脚本
public void PlayerMoveThirdPerson()
{
float h = Input.GetAxisRaw("Horizontal");
float v = Input.GetAxisRaw("Vertical");
Vector3 m_CamForward = Vector3.Scale(cameraT.transform.forward, new Vector3(1, 0, 1)).normalized;
Vector3 m_Move = v * m_CamForward + h * cameraT.transform.right;
if (m_Move.magnitude > 1f)
m_Move = m_Move.normalized;
Vector2 m_Input = new Vector2(h, v).normalized;//获取输入
float targetSpeed = Input.GetKey(KeyCode.LeftShift) ? runSpeed : walkSpeed;//加速或匀速
transform.Translate(m_Move * targetSpeed * Time.deltaTime, Space.World);
//rb.MovePosition(rb.position+m_Move * targetSpeed * Time.deltaTime);//另一种移动方式
if (m_Input != Vector2.zero)
{
ani.SetInteger("AnimationPar", 1);//动画部分,可删减
float targetRotation = Mathf.Atan2(h, v) * Mathf.Rad2Deg + cameraT.transform.eulerAngles.y;
transform.eulerAngles = Vector3.up * Mathf.SmoothDampAngle(transform.eulerAngles.y, targetRotation, ref turnSmoothVelocity, turnSmoothTime);
}
else
{
ani.SetInteger("AnimationPar", 0);
}
if (Input.GetKey(KeyCode.Space))
{
if (ani.GetInteger("AnimationPar") == 1)
{
ani.SetBool("FreeFall", true);
ani.SetBool("Grounded", true);
ani.SetBool("JumpRun", true);
}
else
{
ani.SetBool("JumpRun", false);
ani.SetBool("IsJump", true);
ani.SetBool("Grounded", true);
}
}
else
{
ani.SetBool("IsJump", false);
ani.SetBool("FreeFall", false);
}
transform.GetComponent<Rigidbody>().velocity = Vector3.zero;
Physics.gravity = new Vector3(0, -45, 0);
}
摄像机控制部分
public Transform target;//角色
public Vector3 targetOffset;
public float distance = 5.0f;
public float maxDistance = 20;//缩放
public float minDistance = .6f;//缩放
public float xSpeed = 200.0f;//速度
public float ySpeed = 200.0f;
public int yMinLimit = -80;//限定角度
public int yMaxLimit = 80;
public int zoomRate = 40;
public float zoomDampening = 5.0f;
public float xDeg = 0.0f;//自身的角度记录
public float yDeg = 0.0f;//自身的角度
public float currentDistance;//缩放记录
public float desiredDistance;//缩放
private Quaternion currentRotation;
private Quaternion desiredRotation;
public Quaternion rotation;
private Vector3 position;
public float X;//初始化角度X轴
public float Y;//初始化角度Y轴
public bool isCameraChange = false;
private bool Rot = false;
void LateUpdate()
{
if (Input.GetMouseButton(1))
{
xDeg += (Input.GetAxis("Mouse X") * xSpeed * 0.01f);
yDeg -= (Input.GetAxis("Mouse Y") * ySpeed * 0.01f);
}
yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit);
// 设置相机旋转
desiredRotation = Quaternion.Euler(yDeg, xDeg, 0);
currentRotation = transform.rotation;//记录初始角度
rotation = Quaternion.Lerp(currentRotation, desiredRotation, Time.deltaTime * zoomDampening);
transform.rotation = rotation;
//这里多加了一个鼠标滚轮控制相机缩放的功能(其实是控制相机的距离)
if (!isCameraChange)
{
desiredDistance -= Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime * zoomRate * Mathf.Abs(desiredDistance);
//变焦最小/最大
desiredDistance = Mathf.Clamp(desiredDistance, minDistance, maxDistance);
//平滑变焦
currentDistance = Mathf.Lerp(currentDistance, desiredDistance, Time.deltaTime * zoomDampening);
}
position = new Vector3(target.position.x, 0, target.position.z) - (rotation * Vector3.forward * currentDistance + targetOffset);
transform.position = position;
//这个脚本是角色和摄像机之间有遮挡时改变相机位置,但是有时候会比较突兀,可删减
ProcessMode2();
}
private static float ClampAngle(float angle, float min, float max)
{
if (angle < -360)
angle += 360;
if (angle > 360)
angle -= 360;
return Mathf.Clamp(angle, min, max);
}
public float distanceAway;//相机到角色距离
public Vector3 DisOffset;
/// <summary>
/// 从摄像机到角色
/// </summary>
public void ProcessMode2()
{
RaycastHit hit;
distanceAway = Vector3.Distance(transform.position, target.position);
if (Physics.Linecast(target.position + Vector3.up, transform.position, out hit))
{
string name = hit.collider.gameObject.tag;
if (name != "MainCamera")
{
//如果射线碰撞的不是相机,那么就取得射线碰撞点到玩家的距离
float currentDistance = Vector3.Distance(hit.point, target.position);
if (currentDistance < distanceAway)
{
//Debug.Log("角色遮挡");
transform.position = hit.point + DisOffset;
}
}
}
}
移动端版本
(移动端这里是学习了林新发大佬的方法)
因为是移动端,所以这里使用了摇杆,左摇杆控制角色移动,右摇杆控制摄像机
关于摇杆制作的部分,大家可以看看这篇文章摇杆制作
角色控制代码
public float speed = 1f;
// 转向速度
public float turnSpeed = 20f;
public Animator anim;
// 跟节点
public Transform rootTrans;
// 模型节点
public Transform modelTrans;
// 是否在移动
private bool moving = false;
// 移动向量
private Vector3 moveDirection = Vector3.zero;
// 是否可移动
private bool canMove = true;
void Update()
{
if (canMove && moving)
{
anim.SetInteger("AnimationPar", 1);
rootTrans.position += moveDirection * speed * Time.deltaTime;
modelTrans.forward = Vector3.Lerp(modelTrans.forward, moveDirection, turnSpeed * Time.deltaTime);
}
else
{
anim.SetInteger("AnimationPar", 0);
}
}
public void Move(Vector3 direction)
{
moveDirection = direction;
moving = true;
}
public void Stand()
{
moving = false;
}
相机控制部分代码
// 限制摄像机角度范围
private const float Y_ANGLE_MIN = 10f;
private const float Y_ANGLE_MAX = 50.0f;
// 摄像机看向的物体
public Transform lookAt;
// 摄像机Transform
public Transform camTransform;
// 摄像机距离目标物体的距离
public float distance = 1.2f;
// 原始距离
private float originalDistance;
// 旋转速度
public float rotateSpeed = 0.01f;
private float currentX = 0.0f;
private float currentY = 20.0f;
private bool rotating;
private Vector2 rotateDelta;
private void Start()
{
camTransform = transform;
originalDistance = distance;
}
private void Update()
{
if (rotating)
{
currentX += rotateDelta.x;
currentY += rotateDelta.y;
currentY = Mathf.Clamp(currentY, Y_ANGLE_MIN, Y_ANGLE_MAX);
}
}
public void RotateCam(Vector2 delta)
{
rotateDelta = delta * rotateSpeed;
rotating = true;
}
public void StopRotate()
{
rotating = false;
}
private void LateUpdate()
{
Vector3 dir = new Vector3(0, 0, -distance);
Quaternion rotation = Quaternion.Euler(currentY, currentX, 0);
camTransform.position = lookAt.position + rotation * dir;
camTransform.LookAt(lookAt.position);
}
/// <summary>
/// 修改distnace 镜头调整
/// </summary>
/// <param name="args"></param>
private void OnEventChangeCamDistance(params object[] args)
{
var offset = (float)args[0];
distance = originalDistance + offset * 20f;
}
摇杆控制器脚本
public class GamCtrl : MonoBehaviour
{
private static GamCtrl instance;
public static GamCtrl Instance
{
get
{
if (instance==null)
{
instance = new GamCtrl();
}
return instance;
}
}
public PlayerActionComp2 player;//角色控制脚本
public CameraControl2 cameraCtrl;//摄像机控制脚本
public Rocker rocker;左摇杆
public Rocker world;右摇杆
private void Start()
{
//拖动摇杆
rocker.onDragPcak = (direction) =>
{
var realDirect = cameraCtrl.transform.localToWorldMatrix * new Vector3(direction.x, 0, direction.y);
realDirect.y = 0;
realDirect = realDirect.normalized;
player.Move(realDirect);
};
//停止拖动
rocker.onStopDrag = () => {
player.Stand(); };
world.onDragPcak = (direction) =>
{
cameraCtrl.RotateCam(direction);
};
world.onStopDrag = () =>
{
cameraCtrl.StopRotate();
};
}