1.使用unity中的Standard Assets包中的控制器
这个资源在资源商店中搜Standard Assets就可以下载并导入,在其Characters文件夹中有第一人称和第三人称的控制器,在unity资源面板中找到其预制件拖入层次视图即可。
涉及到的人物控制的内容很全并且也有源代码,如果想自己写玩家控制器这是一个很好的参照,我个人用起来还是自己写的控制器效果比较好。
2.利用unity提供给我们的方法自己做一个:
(1)首先来总结一下unity给我们提供常用的移动、旋转方法:
- Transform.Rotate
public void Rotate (Vector3 eulers, Space relativeTo= Space.Self);
应用一个围绕 Z 轴旋转 eulerAngles.z 度、围绕 X 轴旋转 eulerAngles.x 度、围绕 Y 轴旋转
eulerAngles.y 度(按此顺序)的旋转。relativeTo 确定在游戏对象本地(默认)还是相对于世界空间中的场景来旋转游戏对象。
- Transform.RotateAround
public void RotateAround (Vector3 point, Vector3 axis, float angle);
围绕穿过世界坐标中的 point 的 axis 旋转 angle 度。
eg:绕着世界原点的y轴不断旋转
void Update()
{
// Spin the object around the world origin at 20 degrees/second.
transform.RotateAround(Vector3.zero, Vector3.up, 20 * Time.deltaTime);
}
- Transform.Translate
public void Translate (Vector3 translation, Space relativeTo= Space.Self);
public void Translate (float x, float y, float z, Space relativeTo= Space.Self);
public void Translate (Vector3 translation, Transform relativeTo);
public void Translate (float x, float y, float z, Transform relativeTo);
根据 translation 的方向和距离移动变换。 如果 relativeTo 被省略或设置为Space.Self,则会相对于变换的本地轴来应用该移动。(在场景视图中选择对象时显示的 X、Y 和 Z 轴。) 如果 relativeTo为 Space.World,则相对于世界坐标系应用该移动。
- Transform.LookAt
public void LookAt (Transform target, Vector3 worldUp= Vector3.up);
target 要指向的对象。worldUp 指定向上方向的矢量。 旋转变换,使向前矢量指向 target的当前位置。然后,它旋转变换以将其向上方向矢量指向 worldUp 矢量暗示的方向。 如果省略 worldUp 参数,该函数将使用世界空间的 Y 轴。 worldUp 只是一个提示矢量。如果向前方向垂直于 worldUp,则旋转的向上矢量将仅匹配 worldUp 矢量。
- Vector3.MoveTowards
public static Vector3 MoveTowards (Vector3 current, Vector3 target, float maxDistanceDelta);
current 移动的开始位置。 target 移动的目标位置。 maxDistanceDelta 每次调用 移动current的距离。返回Vector3 新位置。
计算 current 指定的点与 target 指定的点之间的位置,移动距离不超过maxDistanceDelta 指定的距离。使用 MoveTowards 将 current 位置处的对象移向 target位置。通过使用此函数计算的位置来更新每个帧的对象位置,您可以平滑地将其移向目标。使用 maxDistanceDelta参数来控制移动的速度。
请注意,如果将 maxDistanceDelta 设置为负值,则该函数将返回与 target 相反方向的位置。
eg:让当前物体在目标点和与目标点相反的点之间来回走。
void Update()
{
// Move our position a step closer to the target.
float step = speed * Time.deltaTime; // calculate distance to move
transform.position = Vector3.MoveTowards(transform.position, target.position, step);
// Check if the position of the cube and sphere are approximately equal.
if (Vector3.Distance(transform.position, target.position) < 0.001f)
{
// Swap the position of the cylinder.
target.position *= -1.0f;
}
}
- Vector3.Lerp
public static Vector3 Lerp (Vector3 a, Vector3 b, float t);
在两个向量之间进行线性插值。用这个可以由快到慢无限接近目标点(按比例移动) 使用插值 t 在向量 a 和 b 之间进行插值。参数 t 限制在 [0, 1] 范围内。这最常用于查找占两个端点之间距离特定百分比的点(例如,以便在这些点之间逐步移动对象)。
返回Vector3新位置。一定要赋值给应用变换的物体!!!
- Quaternion.AngleAxis
public static Quaternion AngleAxis (float angle, Vector3 axis);
创建一个围绕 axis 旋转 angle 度的旋转。返回四元数。
eg:让物体绕y轴旋转30°。
// Sets the transforms rotation to rotate 30 degrees around the y-axis
transform.rotation = Quaternion.AngleAxis(30, Vector3.up);
- Quaternion.Euler
public static Quaternion Euler (float x, float y, float z);
返回一个围绕 Z 轴旋转 z 度、围绕 X 轴旋转 x 度、围绕 Y 轴旋转 y 度的旋转。
eg:让物体绕y轴旋转30°。
// A rotation 30 degrees around the y-axis
transform.rotation = Quaternion.Euler(0, 30, 0);
- Quaternion.FromToRotation
public static Quaternion FromToRotation (Vector3 fromDirection, Vector3 toDirection);
创建一个从 fromDirection 旋转到 toDirection 的旋转。 通常情况下,您使用该方法对变换进行旋转,使其的一个轴(例如Y 轴)跟随世界空间中的目标方向 /toDirection/。
eg:
// Sets the rotation so that the transform's y-axis goes along the z-axis
transform.rotation = Quaternion.FromToRotation(Vector3.up, transform.forward);
- Quaternion.Lerp
public static Quaternion Lerp (Quaternion a, Quaternion b, float t);
差值旋转(从a到b又快到慢转过去)
- Quaternion.LookRotation
public static Quaternion LookRotation (Vector3 forward, Vector3 upwards= Vector3.up);
参数 forward 要查看的方向。 upwards 定义向上方向的向量。
描述 使用指定的 forward 和 upwards 方向创建旋转。
eg:让物体看向目标 forward即为物体指向目标的方向(涉及到向量的知识)
Vector3 relativePos = target.position - transform.position;
Quaternion rotation = Quaternion.LookRotation(relativePos, Vector3.up);
transform.rotation = rotation;
- Quaternion.RotateTowards
public static Quaternion RotateTowards (Quaternion from, Quaternion to, float maxDegreesDelta);
将旋转 from 向 to 旋转。实现匀速旋转。
将 from 四元数朝 to 旋转 maxDegreesDelta 的角度步长(但请注意, 该旋转不会过冲)。 如果
maxDegreesDelta 为负值,则向远离 to 的方向旋转,直到旋转 恰好为相反的方向
(2)用上面的方法去实现角色控制:
上面已经有这么多旋转移动方法供我们去调用,我们有很多方式去实现根据用户输入方向旋转角色并向前移动的功能。这里我们就来总结一下:
public float moveSpeed = 10;
public float rotateSpeed = 5;
private void Update()
{
int x=Input.GetAxis("Horizontal");
int z=Input.GetAxis("Vertical");
if(x != 0 || z != 0)
{
MovementRotation(x,z);
}
}
private void MovementRotation(int x,int z)
{
Quaternion rotation = Quaternion.LookRotation(new Vector3(x,0,z));
transform.rotation = Quaternion.Lerp(transform.rotation, rotation, rotateSpeed * Time.deltaTime);
Transform.translate(0,0,moveSpeed * Time.deltaTime);
}
其实方法很多,但是可能效果不同,还需要自己多总结多尝试。
3.使用unity中的角色控制器组件CharacterController:
可以直接为角色搜索添加这个组件,这是一个很好用的组件。因为他可使我们轻松进行受碰撞约束的移动,同时不必处理刚体。不必处理刚体太诱人了,因为我们在对刚体属性进行设置时总会出现一些瑕疵(如抖动、穿透…),这些问题用了CharacterController都可以迎刃而解。关于CharacterController可以看这里。
CharacterController有它自己的运动方法public CollisionFlags Move (Vector3 motion);
采用绝对移动增量的更复杂移动函数,相应类的脚本说明。
/// <summary>
/// 注视旋转
/// </summary>
public static void LookTarget(Vector3 target,Transform transform, float rotateSpeed)
{
if (target != Vector3.zero)//不等于自身朝向时
{
Quaternion rotation = Quaternion.LookRotation(target);
transform.rotation = Quaternion.Lerp(transform.rotation, rotation, rotateSpeed);
}
}
//懒得在这对齐了......
//动画系统
public CharacterAnimation chAnim;
//角色控制器
public CharacterController chController;
/// <summary>
/// 移动
/// </summary>
public void Move(float x,float z)//水平面移动不用y
{
if (x != 0 || z != 0)
{
//1.转向前往方向
LookTarget(new Vector3(x, 0, z),transform,rotationSpeed);
//2.向目标移动(-1模拟重力,保障主角贴在地面上,不会飘起来)
Vector3 motion = new Vector3(transform.forward.x, -1, transform.forward.z);
chController.Move(motion * moveSpeed * Time.deltaTime);
//3.播放运动动画
chAnim.PlayAnimation("run");
}
else
{
//不运动播放待机动画
chAnim.PlayAnimation("idle");
}
}
调用时直接调用move方法即可,x,z完全可以上面一样由输入控制类中鼠标、键盘、遥杆…的位置决定。