Unity手遊之路角色控制器
阿新 • • 發佈:2019-01-05
我們要控制角色的移動,可以全部細節都由自己來實現。控制角色模型的移動,同時移動攝影機,改變視角。當然Unity也提供了一些元件,可以讓我們做更少的工作,實現我們所期望的功能。今天我們就一起系統來學習相關的內容吧。
- Charactor Controller(角色控制器)
- 兩個重要的函式
以一定的速度移動。將忽略Y軸上的速度。單位是m/s。重力被自動應用。建議每幀只調用一次Move或者SimpleMove。返回值是是否著地。
例子
2.function Move (motion : Vector3) : CollisionFlagsCharacterController controller= GetComponent<CharacterController>(); Vector3 forward= transform.TransformDirection(Vector3.forward); float curSpeed = speed * Input.GetAxis ("Vertical"); ontroller.SimpleMove(forward * curSpeed);
通過動力來移動控制器。動力只受限制於碰撞。它將沿著碰撞器滑動。這個函式不應用任何重力
如果只是單純控制玩家的移動,那麼用Character Controller足夠了。如果還涉及到視角的切換。Unity提供了相關的元件。在專案中引入Character Controller(Asset->Import Asset),就可以將角色控制器元件匯入我們的專案了。
- 第一人稱控制器
1.刪除預設的攝像機
2.新建一個地形Terrain
3.從角色控制器元件中引入 First Person Controller到專案中
4.拖動First Person Controller到合適的位置
我們就可以看到效果了,以第一人稱的視角移動,巡視整個場景。滑鼠控制整體視角,方向鍵或者wasd按鈕控制攝像機的移動。
- 第三人稱控制器
1.建立一個地形
2.引入3rd Person Controller元件到專案中
3.修改預設攝像機的Tag為MainCamera
4.選中3rd Person Controller元件,將其 Third Person Camera 設定為MainCamera
可以看到效果了,可以看到扮演的角色。方向鍵或者wasd按鍵可以控制角色的移動,同時可以發現整個視角也會跟著移動
效果圖
- 核心程式碼解讀
function Update () {
//獲得鍵盤或者搖桿上的方向量(鍵盤預設是方向鍵和wasd鍵控制方向)
var directionVector = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
//有方向變化
if (directionVector != Vector3.zero) {
//取得方向向量的長度
var directionLength = directionVector.magnitude;
//normal 方向向量(向量/長度)
directionVector = directionVector / directionLength;
//修正長度不大於1
directionLength = Mathf.Min(1, directionLength);
//為了效果更明顯,長度平方擴大
directionLength = directionLength * directionLength;
//用我們修正後的長度來修正方向向量
directionVector = directionVector * directionLength;
}
// 設定移動的方向
motor.inputMoveDirection = transform.rotation * directionVector;
//設定跳躍(預設鍵盤是空格鍵)
motor.inputJump = Input.GetButton("Jump");
}
第三人稱角色控制器ThirdPersonController.js
function Update() {
if (!isControllable)
{
// 清除所有的輸入,如果不處於控制
Input.ResetInputAxes();
}
//按了跳躍鍵
if (Input.GetButtonDown ("Jump"))
{
//設定按下跳躍鍵的時間
lastJumpButtonTime = Time.time;
}
//控制角色的方向
UpdateSmoothedMovementDirection();
//處理重力
ApplyGravity ();
// 處理跳躍邏輯
ApplyJumping ();
//計算實際的動作(移動方向和重力方向的)
var movement = moveDirection * moveSpeed + Vector3 (0, verticalSpeed, 0) + inAirVelocity;
movement *= Time.deltaTime;
// 移動角色
var controller : CharacterController = GetComponent(CharacterController);
collisionFlags = controller.Move(movement);
// 動畫處理
if(_animation) {
if(_characterState == CharacterState.Jumping) //跳躍
{
if(!jumpingReachedApex) {//沒到達最高點,繼續向上
_animation[jumpPoseAnimation.name].speed = jumpAnimationSpeed;
_animation[jumpPoseAnimation.name].wrapMode = WrapMode.ClampForever;
_animation.CrossFade(jumpPoseAnimation.name);
} else {//到了最高點,速度方向改變
_animation[jumpPoseAnimation.name].speed = -landAnimationSpeed;
_animation[jumpPoseAnimation.name].wrapMode = WrapMode.ClampForever;
_animation.CrossFade(jumpPoseAnimation.name);
}
}
else
{
if(controller.velocity.sqrMagnitude < 0.1) {//沒有方向移動
_animation.CrossFade(idleAnimation.name);//空閒狀態
}
else
{
if(_characterState == CharacterState.Running) {//奔跑
_animation[runAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0, runMaxAnimationSpeed);
_animation.CrossFade(runAnimation.name);
}
else if(_characterState == CharacterState.Trotting) {//疾走
_animation[walkAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0, trotMaxAnimationSpeed);
_animation.CrossFade(walkAnimation.name);
}
else if(_characterState == CharacterState.Walking) {//普通走動
_animation[walkAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0, walkMaxAnimationSpeed);
_animation.CrossFade(walkAnimation.name);
}
}
}
}
//在地上
if (IsGrounded())
{
//旋轉方向
transform.rotation = Quaternion.LookRotation(moveDirection);
}
else
{
//在空中忽略y軸旋轉
var xzMove = movement;
xzMove.y = 0;
if (xzMove.sqrMagnitude > 0.001)
{
transform.rotation = Quaternion.LookRotation(xzMove);
}
}
// 跳躍狀態,剛好到達地面
if (IsGrounded())
{
//記錄到達地面的時間
lastGroundedTime = Time.time;
//空中的速度設定為0
inAirVelocity = Vector3.zero;
//更改相關狀態
if (jumping)
{
jumping = false;
SendMessage("DidLand", SendMessageOptions.DontRequireReceiver);
}
}
}
第三人控制器攝像機指令碼ThirdPersonCamera.js
function Apply (dummyTarget : Transform, dummyCenter : Vector3)
{
// 沒有目標
if (!controller)
return;
//目標中心和頂點
var targetCenter = _target.position + centerOffset;
var targetHead = _target.position + headOffset;
//計算目標旋轉角度和當前角度
var originalTargetAngle = _target.eulerAngles.y;
var currentAngle = cameraTransform.eulerAngles.y;
// 調整目標的真實角度
var targetAngle = originalTargetAngle;
//按了Fire2(alt)攝像機的方向改變會加快
if (Input.GetButton("Fire2"))
snap = true;
if (snap)
{
// 靠近角色了,重置snap
if (AngleDistance (currentAngle, originalTargetAngle) < 3.0)
snap = false;
//計算當前角度
currentAngle = Mathf.SmoothDampAngle(currentAngle, targetAngle, angleVelocity, snapSmoothLag, snapMaxSpeed);
}
// Normal 攝像機動作
else
{
//延遲一點時間
if (controller.GetLockCameraTimer () < lockCameraTimeout)
{
targetAngle = currentAngle;
}
// 向後走的時候鎖住攝像機
if (AngleDistance (currentAngle, targetAngle) > 160 && controller.IsMovingBackwards ())
targetAngle += 180;//旋轉180
//插值改變相機角度
currentAngle = Mathf.SmoothDampAngle(currentAngle, targetAngle, angleVelocity, angularSmoothLag, angularMaxSpeed);
}
//當跳躍時
// When jumping don't move camera upwards but only down!
if (controller.IsJumping ())
{
// 計算目標的高度
var newTargetHeight = targetCenter.y + height;
if (newTargetHeight < targetHeight || newTargetHeight - targetHeight > 5)
targetHeight = targetCenter.y + height;
}
// 走動時,改變高度
else
{
targetHeight = targetCenter.y + height;
}
// 計算當前高度
var currentHeight = cameraTransform.position.y;
currentHeight = Mathf.SmoothDamp (currentHeight, targetHeight, heightVelocity, heightSmoothLag);
// 按角度旋轉、
var currentRotation = Quaternion.Euler (0, currentAngle, 0);
//更新相機位置
cameraTransform.position = targetCenter;
cameraTransform.position += currentRotation * Vector3.back * distance;
// 設定相機的高度
cameraTransform.position.y = currentHeight;
//攝像機一直朝向目標
SetUpRotation(targetCenter, targetHead);
}
- 總結
角色控制,可以方便的控制遊戲的視角。在很多遊戲中,可以直接使用該元件,減少我們的重複開發工作
- 原始碼
http://pan.baidu.com/s/1BwArJ
- 參考文件