游戏角色
一、导入资源
1、获取资源动画人物
2、创建项目
3、导入资源:人物、走、跑、休息
(1) 新建文件夹。Import Asset
(2) 将资源导入
二、设置人物
1、新建场景。Farm
2、增加角色,命名为Player
3、点击Import Asset中的角色,选中材质
、
4、点击Extract Textures,在弹出框点击“选择”。在弹出框中选择Fix Now
5、再次点击Import Asset中的角色,选中Rig,将Animation Type设置为Humanoid
6、将Avatar Definetion 设置为Create From This Model,apply
7、设置Walking、Running和Idle
8、新建Prefabs文件夹,将角色制成预制体
9、设置摄像机
三、设置人物动画
1、新建文件夹Animation,在Animation文件夹下新建文件夹Controllers
2、在Controller文件夹下Create Animator Controller,命名为Player
3、选中Hierarchy中的人物,在Inspector面板中给Animator中的Controller选择Player
4、打开Controller文件夹下的Player,此时还没有动画
5、找到Walking、Running和Idle的资源,点击右侧小三角,复制mixano.com,分别重命名为Walking、Running和Idle,将复制的Walking、Running和Idle转移到Animation文件夹
6、分别选择Walking、Running和Idle,设置循环播放(Loop Pose也勾选上)
7、打开Controller文件夹下的Player,依次将Idle(默认)、Walking、Running拖入新界面
8、选择Parameters,依次添加Float和Bool,分别命名为Speed和Running,
调节三者的Speed值(步伐快慢)一般与脚本设置的Speed一致
9、设置条件,选中Idle,右击,选择Make Transition,单击Walking
10、选中Idle到Walking的箭头,添加Conditons,设置Speed的Greater为0.001(当速度大于0.001时行走)这个可以参照角色添加的组件中的Min Move Distance(改为0.01)
取消勾选Has Exit Time
11、选中Walking,右击,选择Make Transition,单击Idle
12、选中Walking到Idle的箭头,添加Conditons,设置Speed的less为0.001(速度小于0.001时站立 ),取消勾选Has Exit Time。这一步的数值需要反复调整
四、控制人物行走
1、给人物预制体,添加Character Controller(角色控制器)组件,调节参数至笼罩全身
2、新建文件夹Scripts,给人物预制体添加PlayerController.cs组件
public class PlayerController : MonoBehaviour
{
private CharacterController controller;
private Animator animator;
void Start()
{
controller = GetComponent<CharacterController>();
animator = GetComponent<Animator>();
}
void Update()
{
Move();
}
public void Move()
{
}
}
3、回到Unity-Edit-Projects Setting-Input Manager,观察水平和垂直方向上字母的写法
4、打开PlayerController.cs,设定角色行走
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
private CharacterController controller;
private Animator animator;
private float moveSpeed=2f;
void Start()
{
controller = GetComponent<CharacterController>();
animator = GetComponent<Animator>();
}
void Update()
{
Move();
}
public void Move()
{
float horizontal = Input.GetAxisRaw("Horizontal");
float vertical = Input.GetAxisRaw("Vertical");
Vector3 dir = new Vector3(horizontal, 0, vertical).normalized;
Vector3 velocity = moveSpeed * Time.deltaTime * dir;
if (dir.magnitude > 0.1f)
{
//朝向哪个方向
transform.rotation =Quaternion.LookRotation(dir);//测试一下
//运动
controller.Move(velocity);
}
}
}
几点说明
(1) Input.GetAxisRaw("Horizontal")
作用
精确地控制输入(如在一个物理模拟中),或想完全避免Unity的平滑处理
解析
Input.GetAxis("Horizontal") :
平滑的角色移动或摄像机旋转效果
通过Unity的 Input Manager(输入管理器)自定义轴的行为和敏感度,会影响到GetAxis
和GetAxisRaw
的行为。
例如,改变轴的死区(deadzone),以减少轻微的输入波动。
这些设置可以在Unity的编辑器中的"Edit" -> "Project Settings" -> "Input"菜单下找到
(2) if(dir.magnitude > 0.1f)
:
作用
检查 dir
的长度是否大于0.1,判断用户输入是否足够显著,从而防止因玩家手部的微小移动或设备的噪声而导致的误操作
解析
dir.magnitude
计算这个向量长度(或模)的属性。
Vector3
下:计算的是三维空间中从原点(0,0,0)到该向量所表示的点之间的欧几里得距离。
简单地说就是两点之间的直线长度
(3) CharacterController
组件
作用
用于处理角色(通常是第一人称或第三人称角色)在物理环境中的移动
详解
简化角色移动:与直接使用刚体(Rigidbody)和碰撞器(Collider)相比,CharacterController
提供了一个更简化的方式来处理角色的移动。它允许你直接设置角色的速度和位置,而无需担心物理计算的复杂性
支持楼梯和斜坡:能够自动处理角色在楼梯和斜坡上的移动,而无需额外的脚本代码。
碰撞检测:提供了与场景中其他物体的碰撞检测功能。
可以通过监听 OnControllerColliderHit
事件来检测角色何时与另一个物体发生碰撞。
防止角色穿过墙壁: CharacterController
会处理角色与场景中的碰撞,
可以确保角色不会穿过墙壁或其他障碍物
适用于非物理驱动的场景:若不希望角色受到物理引擎的完全控制(如在平台游戏中),CharacterController
提供了一个中间选项,允许你控制角色的移动,同时仍然受益于碰撞检测和防止穿透墙壁的功能
限制
不支持复杂的物理交互(如旋转力或扭矩),并且可能不适用于需要高度精确物理模拟的场景。
在这些情况下,一般需要使用刚体和碰撞器来替代 CharacterController
5、关联动画速度(注意Animator中的单词)与脚本的速度
public void Move()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
Vector3 dir = new Vector3(horizontal,0, vertical).normalized;
Vector3 velocity = moveSpeed * Time.deltaTime * dir;
if(dir.magnitude >0.1f)
{
transform.rotation= Quaternion.LookRotation(dir);
controller.Move(velocity);
}
animator.SetFloat("Speed", velocity.magnitude);//新增。使animator的Speed与velocity.magnitude关联
}
五、控制奔跑
1、添加加速键
(1) Edit-Project Setting-Input Manager
(2) 更改Size由18改为19(增加一行)
(3) 选中新增行(最后一个Cancel)更改Name为Sprint,设置Positive Button为left shift,Alt Positive Button为 right shift
(4) 回到PlayerController.cs,设置加速(还不能奔跑)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
private CharacterController controller;
private Animator animator;
private float moveSpeed = 2f;
//在Unity的Inspector面板显示标题
[Header("Movement System")]
public float walkSpeed = 2f;
public float runSpeed = 4f;
void Start()
{
controller = GetComponent<CharacterController>();
animator = GetComponent<Animator>();
}
void Update()
{
Move();
}
public void Move()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
Vector3 dir = new Vector3(horizontal, 0, vertical).normalized;
Vector3 velocity = moveSpeed*Time.deltaTime*dir;
//设置加速
if (Input.GetButton("Sprint"))
{
moveSpeed = runSpeed;
}
else
{
moveSpeed = walkSpeed;
}
if(dir.magnitude > 0.1f)
{
transform.rotation = Quaternion.LookRotation(dir);
controller.Move(velocity);
}
animator.SetFloat("Speed",velocity.magnitude);
}
}
2、设置奔跑动画
(1) 设置动画:由步行到奔跑和奔跑到步行
(2) 回到PlayerController.cs,关联动画
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
private CharacterController controller;
private Animator animator;
private float moveSpeed = 2f;
[Header("Movement System")]
public float walkSpeed = 2f;
public float runSpeed = 4f;
void Start()
{
controller = GetComponent<CharacterController>();
animator = GetComponent<Animator>();
}
void Update()
{
Move();
}
public void Move()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
Vector3 dir = new Vector3(horizontal, 0, vertical).normalized;
Vector3 velocity = moveSpeed*Time.deltaTime*dir;
if (Input.GetButton("Sprint"))
{
moveSpeed = runSpeed;
animator.SetBool("Running",true);//与动画关联
}
else
{
moveSpeed = walkSpeed;
animator.SetBool("Running",false);//与动画关联
}
if(dir.magnitude > 0.1f)
{
transform.rotation = Quaternion.LookRotation(dir);
controller.Move(velocity);
}
animator.SetFloat("Speed",velocity.magnitude);
}
}
(3) 添加奔跑到Idle
六、相机跟随
1、Reset人物
2、调整相机的Transform
3、给Main Camera增加CameraController.cs组件(注意z轴的纵深)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraController : MonoBehaviour
{
public float offsetz = 6f;
Transform playerPos;
void Start()
{
playerPos = FindObjectOfType<PlayerController>().transform;
}
void Update()
{
FollowPlayer();
}
void FollowPlayer()
{
Vector3 targerPos = new Vector3(playerPos.position.x, transform.position.y, playerPos.position.z-offsetz);
transform.position = targerPos;
}
}
4、增加平滑过渡效果
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraController : MonoBehaviour
{
public float offsetz = 6f;
public float smoothing = 8f;
Transform playerPos;
void Start()
{
playerPos = FindObjectOfType<PlayerController>().transform;
}
void Update()
{
FollowPlayer();
}
void FollowPlayer()
{
Vector3 targetPos = new Vector3(playerPos.position.x, transform.position.y, playerPos.position.z-offsetz);
transform.position = Vector3.Lerp(transform.position, targetPos, smoothing*Time.deltaTime);
}
}
Vector3.Lerp(transform.position, targetPos, smoothing*Time.deltaTime);
Vector3.Lerp :
在两个Vector3
值之间进行线性插值,
用于在物体的当前位置和目标位置之间平滑过渡
smoothing*Time.deltaTime :
每帧移动的“进度”。
控制过渡的平滑度和进度