Unity3d之角色控制器
阿新 • • 發佈:2019-01-10
我們要控制角色的移動,可以全部細節都由自己來實現。控制角色模型的移動,同時移動攝影機,改變視角。當然Unity也提供了一些元件,可以讓我們做更少的工作,實現我們所期望的功能。今天我們就一起系統來學習相關的內容吧。
- Charactor Controller(角色控制器)
- 兩個重要的函式
以一定的速度移動。將忽略Y軸上的速度。單位是m/s。重力被自動應用。建議每幀只調用一次Move或者SimpleMove。返回值是是否著地。
例子
- CharacterController controller= GetComponent<CharacterController>();
- Vector3 forward= transform.TransformDirection(Vector3.forward);
-
float curSpeed = speed * Input.GetAxis (
- 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按鍵可以控制角色的移動,同時可以發現整個視角也會跟著移動
效果圖
- 核心程式碼解讀
[javascript] view plain copy
- 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
[javascript] view plain copy- 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);
- }
- elseif(_characterState == CharacterState.Trotting) {//疾走
- _animation[walkAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0, trotMaxAnimationSpeed);
- _animation.CrossFade(walkAnimation.name);
- }
- elseif(_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);
- }
- }
- }
- 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)
- {
- // 靠近角色了,重置sna