核心1、新建工程,取名Exercise_3D。
2、新建个文件夹(3D_Assets),将所有素材资源,导入或拖入。
3、新建一个3DObject——Plane,取名(Ground)作为地面。
4、新建一个空物体,取名Player,然后将3D人物模型拖入,作为子物体。
5、对Player添加Animator组件和CharacterController组件。
5、选中Player,在Animator窗口,新建BlendTree(混合树动画),并将 idle动画、walk动画、run动画拖入。然后 创建Speed,作为速度判断的阀值条件。Jump动画拖入,创建Bool条件。
6、对 Player添加脚本(PlayerController)。
1.获取private CharacterController、并创建其他需要的条件;
2.Start里:_characterController=GetComponent<CharacterController>();
3.新建方法PlayerMove(); 里面写 移动和转向代码、鼠标旋转视角代码、动画播放。***(移动和跳跃代码放FixedUpdate里)
3.1.动画播放:使用混合树动画,用BlandSpeed做切换动画的条件,并 写播放动画的代码
7、在Player脚本里,新建方法playerJump(); 里面写 跳跃代码、动画播放。
1.创建 bool值(isJump,表示是否按下跳跃键),创建float值(jumpVelocity表示跳跃速度;jumpForce表示跳跃时给的力)
2.创建3个if方法,表示:跳跃、受重力影响下落、停止播放跳跃动画。
8、在Player脚本里,新建方法CameraRotation(); 里面写 相机的跟随和旋转代码。(相机方法在LateUpdate里调用)
1.新建空物体(取名Follow),作为Player的子物体,挂在人物头顶(作为相机跟随的对象)。
2.下载Cinema组件,并添加CinemachineVirtualCamera组件(取名PlayerFollowCamera),并进行一些设置。
3.在方法内写脚本
*******(目前来说,简单的移动、跳跃和相机跟随就完成了,没有判断是否接触地面,所以现在可以无限跳跃)******
代码:
public class PlayerController : MonoBehaviour
{
private CharacterController _characterController;
public float walkSpeed = 2f;//走路速度
public float runSpeed = 5f;//跑步速度
public float smoothTime = 0.2f;//平滑转向用时
public float targetSpeed;//当前速度
private Vector3 targetDirection;//当前前进的方向
private float targetRotation;//当前旋转角度
private float currentVelocity;//当前旋转速度(使旋转平滑用的)(固定写法,必须要的)
public bool isRun;//是否按下跑步键
public bool isJump;//是否按下跳跃键
public float jumpForce = 10.0f;//跳跃力
private float jumpVelocity = -1.0f;//跳跃速度
public float _gravity = -9.8f;//重力
private Animator _animator;
private float animationBlend;//混合树动画条件
public GameObject _mainCamera;//获取 主相机
private float _cinemachineTargetYaw;//获取 鼠标输入X(水平左右旋转)(偏航)
private float _cinemachineTargetPitch;//获取 鼠标输入Y(竖直上下旋转)(倾斜、坠落)
public float mouseMoveSpeed = 2;//鼠标旋转的速度
public float bottomClamp = -30.0f;//鼠标向下限制,你能把相机向下移动多少
public float topClamp = 70.0f;//鼠标向上限制,你能把相机向上移动多少
public GameObject cinemachineCameraTarget;//获取 相机跟随的目标
private void Start()
{
_characterController = GetComponent<CharacterController>();//初始化组件
_animator = GetComponent<Animator>();
}
private void Update()
{
IsRun();
IsJump();
}
private void FixedUpdate()
{
PlayerMove();
PlayerJump();
}
private void LateUpdate()
{
CameraRotation();//鼠标旋转视角
}
//是否按下了 跑步键(Shift)
private void IsRun()
{
if (Input.GetKeyDown(KeyCode.LeftShift))
{
isRun = true;
}
if (Input.GetKeyUp(KeyCode.LeftShift))
{
isRun = false;
}
}
//是否按下了 跳跃键(空格)
private void IsJump()
{
if (Input.GetButtonDown("Jump"))
{
isJump = true;
}
}
//玩家 移动
public void PlayerMove()
{
//获取 前后左右 的键盘输入
Vector2 _input = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
Vector2 inputDir = _input.normalized;//向量单位化
//根据 是否按下跑步键,判断玩家此时状态(跑步?还是走路?)
targetSpeed = isRun ? runSpeed : walkSpeed;
//如果没有输入,将目标速度设置为0
if (inputDir == Vector2.zero)
{
targetSpeed = 0.0f;
}
//只用于 混合树动画 的Speed值
animationBlend = Mathf.Lerp(0.0f, targetSpeed, Time.deltaTime * 95.0f);
if (inputDir != Vector2.zero)
{
//获取 转动的角度(+按住方向键时玩家突然转动鼠标时,相机跟随转动) 弧度转换为度
targetRotation = Mathf.Atan2(inputDir.x, inputDir.y) * Mathf.Rad2Deg + _mainCamera.transform.eulerAngles.y;
//平滑旋转(用于欧拉角的)
float _rotation = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetRotation, ref currentVelocity, smoothTime);
//将平滑旋转 (以欧拉角的形式)给到 玩家
transform.rotation = Quaternion.Euler(0.0f, _rotation, 0.0f);
}
//获取 前进的方向(这是一个Vector3)
targetDirection = Quaternion.Euler(0.0f, targetRotation, 0.0f) * Vector3.forward;
//动起来(+垂直速度(下落))
_characterController.Move(targetDirection.normalized * targetSpeed * Time.deltaTime + new Vector3(0.0f, jumpVelocity, 0.0f) * Time.deltaTime);
_animator.SetFloat("Speed", animationBlend);//移动动画
}
//玩家 跳跃
public void PlayerJump()
{
if (isJump)
{
//如果按下了 跳跃键
jumpVelocity = jumpForce;//获得跳跃力
_animator.SetBool("Jump", true);//跳跃动画
isJump = false;//防止长按一直跳
}
if (jumpVelocity < 50.0f)
{
jumpVelocity += _gravity * Time.deltaTime;//受重力影响,使玩家一直有一个下坠力
//Debug.Log(jumpVelocity);
}
if (jumpVelocity < 0)
{
_animator.SetBool("Jump", false);//停止播放 跳跃动画
}
}
//鼠标旋转视角
public void CameraRotation()
{
_cinemachineTargetYaw += Input.GetAxis("Mouse X") * mouseMoveSpeed;//获取 鼠标输入X(水平左右旋转)
_cinemachineTargetPitch -= Input.GetAxis("Mouse Y") * mouseMoveSpeed;//获取 鼠标输入Y(竖直上下旋转)
//限制鼠标角度
_cinemachineTargetYaw = ClampAngle(_cinemachineTargetYaw, float.MinValue, float.MaxValue);
_cinemachineTargetPitch = ClampAngle(_cinemachineTargetPitch, bottomClamp, topClamp);
//让相机跟随的目标旋转(相机也就跟着转)*****************(鼠标的旋转传给Follow,相机是跟随Follow旋转的,也就是Follow旋转,相机才旋转)
cinemachineCameraTarget.transform.rotation = Quaternion.Euler(_cinemachineTargetPitch, _cinemachineTargetYaw, 0.0f);
}
//限制鼠标角度
private static float ClampAngle(float Angle, float MinAngle, float MaxAngle)
{
if (Angle < -360f)
{
Angle += 360f;
}
if (Angle > 360f)
{
Angle -= 360f;
}
return Mathf.Clamp(Angle, MinAngle, MaxAngle);
}
}
跟随相机的设置: