Unity第三人称角色控制

游戏角色通常有两种控制方式,第一人称角色控制和第三人称角色控制。这篇文章介绍一下后者。不过即使是第三人称角色控制也应该有不同的控制模式,具体的应该和游戏本身相关。这里实现的第三人称控制应该是属于一般的MMORPG。

首先想想一般的MMORPG游戏中,角色是如何移动的。

W: 控制角色向前移动

S: 控制角色向后移动

A: 控制角色向左移动

D: 控制角色向右移动

角色和摄像机应该始终朝着鼠标所指示的方向

W\S\A\D和鼠标控制角色移动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class PlayerController : MonoBehaviour
{
Transform cameraTransform; //相机的Transform
CharacterController controller;
public float speed = 8.0f; //移动的速度
void Start()
{
cameraTransform = GameObject.FindGameObjectWithTag("MainCamera").transform;
controller = GetComponent<CharacterController>();
}
void Update()
{
if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.D))
{
if (Input.GetKey(KeyCode.W))
{
//根据主相机的朝向决定人物的移动方向,下同
controller.transform.eulerAngles = new Vector3(0, cameraTransform.transform.eulerAngles.y, 0);
}
if (Input.GetKey(KeyCode.S))
{
controller.transform.eulerAngles = new Vector3(0, cameraTransform.transform.eulerAngles.y + 180f, 0);
}
if (Input.GetKey(KeyCode.A))
{
controller.transform.eulerAngles = new Vector3(0, cameraTransform.transform.eulerAngles.y + 270f, 0);
}
if (Input.GetKey(KeyCode.D))
{
controller.transform.eulerAngles = new Vector3(0, cameraTransform.transform.eulerAngles.y + 90f, 0);
}
controller.Move(transform.forward * Time.deltaTime * speed);
}
else
{
//静止状态
}
}
}

摄像机跟随鼠标和角色移动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
public class FollowPlayer : MonoBehaviour
{
public Transform player;
public Vector3 playerOffset = Vector3.zero;
public float distance = 10f;
public float minDistance = 2f;
public float maxDistance = 15f;
public float zoomSpeed = 1f;
// 在X轴上的移动速度
public float xSpeed = 200.0f;
// 在Y轴上的移动速度
public float ySpeed = 200.0f;
public bool allowYTilt = true;
public float yMinLimit = 20f;
public float yMaxLimit = 80f;
// 需要旋转的角度
private float x = 0f;
private float y = 0f;
// 旋转的目标角度
private float targetX = 0f;
private float targetY = 0f;
private float targetDistance = 0f;
// 旋转速度
private float xVelocity = 1f;
private float yVelocity = 1f;
// 缩放速度
private float zoomVelocity = 1f;
void Start()
{
Vector3 angles = transform.eulerAngles;
targetX = angles.x;
targetY = ClampAngle(angles.y, yMinLimit, yMaxLimit);
targetDistance = distance;
}
void LateUpdate()
{
float scroll = Input.GetAxis("Mouse ScrollWheel");
if (scroll > 0f)
{
targetDistance -= zoomSpeed;
}
else if (scroll < 0f)
{
targetDistance += zoomSpeed;
}
targetDistance = Mathf.Clamp(targetDistance, minDistance, maxDistance);
if (Input.GetMouseButton(1) || (Input.GetMouseButton(0) && (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl))))
{
targetX += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
if (allowYTilt)
{
targetY -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
targetY = ClampAngle(targetY, yMinLimit, yMaxLimit);
}
}
x = Mathf.SmoothDampAngle(x, targetX, ref xVelocity, 0.3f);
if (allowYTilt)
{
y = Mathf.SmoothDampAngle(y, targetY, ref yVelocity, 0.3f);
}
else
{
y = targetY;
}
Quaternion rotation = Quaternion.Euler(y, x, 0);
distance = Mathf.SmoothDamp(distance, targetDistance, ref zoomVelocity, 0.5f);
Vector3 position = rotation * new Vector3(0, 0, -distance) + player.position + playerOffset;
transform.rotation = rotation;
transform.position = position;
}
private float ClampAngle(float angle, float min, float max)
{
if (angle < -360) angle += 360;
if (angle > 360) angle -= 360;
return Mathf.Clamp(angle, min, max);
}
}