2017-05-31 50 views
0

嗨,我有一個場景,其中我需要限制第三人稱控制器的角度旋轉。當我按左右輸入鍵時,它將旋轉90度。我希望旋轉45度。有人能幫助我,在哪條線上發生角度旋轉。如何限制第三方控制器的角度旋轉

這裏我的代碼:

public class ThirdPersonShooter : MonoBehaviour 
{ 

    public AnimationClip idleAnimation; 
    public AnimationClip walkAnimation; 
    public AnimationClip runAnimation; 
    public AnimationClip jumpPoseAnimation; 

    public float walkMaxAnimationSpeed = 0.75F; 
    public float trotMaxAnimationSpeed = 1F; 
    public float runMaxAnimationSpeed = 1F; 
    public float jumpAnimationSpeed = 1F; 
    public float landAnimationSpeed = 1F; 

    private Animation _animation; 

    enum CharacterState 
    { 
     Idle = 0, 
     Walking = 1, 
     Trotting = 2, 
     Running = 3, 
     Jumping = 4, 
    } 
    private CharacterState _characterState; 
    // The speed when walking 
    public float walkSpeed = 2.0F; 
    // after trotAfterSeconds of walking we trot with trotSpeed 
    public float trotSpeed = 4.0F; 
    // when pressing "Fire3" button (cmd) we start running 
    public float runSpeed = 6.0F; 

    public float inAirControlAcceleration = 3.0F; 

    // How high do we jump when pressing jump and letting go immediately 
    public float jumpHeight = 0.5F; 

    // The gravity for the character 
    public float gravity = 20.0F; 
    // The gravity in controlled descent mode 
    public float speedSmoothing = 10.0F; 
    public float rotateSpeed = 500.0F; 
    public float trotAfterSeconds = 3.0F; 

    public bool canJump = true; 

    private float jumpRepeatTime = 0.05F; 
    private float jumpTimeout = 0.15F; 
    private float groundedTimeout = 0.25F; 

    // The camera doesnt start following the target immediately but waits for a split second to avoid too much waving around. 
    private float lockCameraTimer = 0.0F; 

    // The current move direction in x-z 
    private Vector3 moveDirection = Vector3.zero; 
    // The current vertical speed 
    private float verticalSpeed = 0.0F; 
    // The current x-z move speed 
    private float moveSpeed = 0.0F; 

    // The last collision flags returned from controller.Move 
    private CollisionFlags collisionFlags; 

    // Are we jumping? (Initiated with jump button and not grounded yet) 
    private bool jumping = false; 
    private bool jumpingReachedApex = false; 

    // Are we moving backwards (This locks the camera to not do a 180 degree spin) 
    private bool movingBack = false; 
    // Is the user pressing any keys? 
    private bool isMoving = false; 
    // When did the user start walking (Used for going into trot after a while) 
    private float walkTimeStart = 0.0F; 
    // Last time the jump button was clicked down 
    private float lastJumpButtonTime = -10.0F; 
    // Last time we performed a jump 
    private float lastJumpTime = -1.0F; 


    // the height we jumped from (Used to determine for how long to apply extra jump power after jumping.) 
    private float lastJumpStartHeight = 0.0F; 


    private Vector3 inAirVelocity = Vector3.zero; 

    private float lastGroundedTime = 0.0F; 


    private bool isControllable = true; 

    // Use this for initialization 
    void Awake() 
    { 
     moveDirection = transform.TransformDirection(Vector3.forward); 

     _animation = GetComponent<Animation>(); 
     if (!_animation) 
      Debug.Log("The character you would like to control doesn't have animations. Moving her might look weird."); 

     /* 
    public AnimationClip idleAnimation; 
    public AnimationClip walkAnimation; 
    public AnimationClip runAnimation; 
    public AnimationClip jumpPoseAnimation; 
     */ 
     if (!idleAnimation) 
     { 
      _animation = null; 
      Debug.Log("No idle animation found. Turning off animations."); 
     } 
     if (!walkAnimation) 
     { 
      _animation = null; 
      Debug.Log("No walk animation found. Turning off animations."); 
     } 
     if (!runAnimation) 
     { 
      _animation = null; 
      Debug.Log("No run animation found. Turning off animations."); 
     } 
     if (!jumpPoseAnimation && canJump) { 
      _animation = null; 
      Debug.Log("No jump animation found and the character has canJump enabled. Turning off animations."); 
     } 

    } 
    void UpdateSmoothedMovementDirection() 
    { 
     Transform cameraTransform = Camera.main.transform; 
     bool grounded = IsGrounded(); 

     // Forward vector relative to the camera along the x-z plane 
     Vector3 forward = cameraTransform.TransformDirection(Vector3.forward); 
     forward.y = 0; 
     forward = forward.normalized; 

     // Right vector relative to the camera 
     // Always orthogonal to the forward vector 
     Vector3 right = new Vector3(forward.z, 0, -forward.x); 

     float v = Input.GetAxisRaw("Vertical"); 
     float h = Input.GetAxisRaw("Horizontal"); 

     // Are we moving backwards or looking backwards 
     if (v < -0.2f) 
      movingBack = true; 
     else 
      movingBack = false; 

     bool wasMoving = isMoving; 
     isMoving = Mathf.Abs(h) > 0.1f || Mathf.Abs(v) > 0.1f; 

     // Target direction relative to the camera 
     Vector3 targetDirection = h * right + v * forward; 

     // Grounded controls 
     if (grounded) 
     { 
      // Lock camera for short period when transitioning moving standing still 
      lockCameraTimer += Time.deltaTime; 
      if (isMoving != wasMoving) 
       lockCameraTimer = 0.0f; 

      // We store speed and direction seperately, 
      // so that when the character stands still we still have a valid forward direction 
      // moveDirection is always normalized, and we only update it if there is user input. 
      if (targetDirection != Vector3.zero) 
      { 
       // If we are really slow, just snap to the target direction 
       if (moveSpeed < walkSpeed * 0.9f && grounded) 
      { 
        moveDirection = targetDirection.normalized; 
       } 
      // Otherwise smoothly turn towards it 
      else 
      { 
        moveDirection = Vector3.RotateTowards(moveDirection, targetDirection, rotateSpeed * Mathf.Deg2Rad * Time.deltaTime, 1000); 

        moveDirection = moveDirection.normalized; 
       } 
      } 

      // Smooth the speed based on the current target direction 
      float curSmooth = speedSmoothing * Time.deltaTime; 

      // Choose target speed 
      //* We want to support analog input but make sure you cant walk faster diagonally than just forward or sideways 
      float targetSpeed = Mathf.Min(targetDirection.magnitude, 1.0f); 

      _characterState = CharacterState.Idle; 

      // Pick speed modifier 
      if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) 
      { 
       targetSpeed *= runSpeed; 
       _characterState = CharacterState.Running; 
      } 
      else if (Time.time - trotAfterSeconds > walkTimeStart) 
      { 
       targetSpeed *= trotSpeed; 
       _characterState = CharacterState.Trotting; 
      } 
      else 
      { 
       targetSpeed *= walkSpeed; 
       _characterState = CharacterState.Walking; 
      } 

      moveSpeed = Mathf.Lerp(moveSpeed, targetSpeed, curSmooth); 

      // Reset walk time start when we slow down 
      if (moveSpeed < walkSpeed * 0.3f) 
       walkTimeStart = Time.time; 
     } 
     // In air controls 
     else 
     { 
      // Lock camera while in air 
      if (jumping) 
       lockCameraTimer = 0.0f; 

      if (isMoving) 
       inAirVelocity += targetDirection.normalized * Time.deltaTime * inAirControlAcceleration; 
     } 



    } 
    void ApplyJumping() 
    { 
     // Prevent jumping too fast after each other 
     if (lastJumpTime + jumpRepeatTime > Time.time) 
      return; 

     if (IsGrounded()) 
     { 
      // Jump 
      // - Only when pressing the button down 
      // - With a timeout so you can press the button slightly before landing  
      if (canJump && Time.time < lastJumpButtonTime + jumpTimeout) { 
       verticalSpeed = CalculateJumpVerticalSpeed(jumpHeight); 
       SendMessage("DidJump", SendMessageOptions.DontRequireReceiver); 
      } 
     } 
    } 
    void ApplyGravity() 
    { 
     if (isControllable) // don't move player at all if not controllable. 
     { 
      // Apply gravity 
      bool jumpButton = Input.GetButton("Jump"); 


      // When we reach the apex of the jump we send out a message 
      if (jumping && !jumpingReachedApex && verticalSpeed <= 0.0f) 
     { 
       jumpingReachedApex = true; 
       SendMessage("DidJumpReachApex", SendMessageOptions.DontRequireReceiver); 
      } 

      if (IsGrounded()) 
       verticalSpeed = 0.0f; 
      else 
       verticalSpeed -= gravity * Time.deltaTime; 
     } 
    } 
    float CalculateJumpVerticalSpeed(float targetJumpHeight) 
    { 
     // From the jump height and gravity we deduce the upwards speed 
     // for the character to reach at the apex. 
     return Mathf.Sqrt(2 * targetJumpHeight * gravity); 
    } 
    void DidJump() 
    { 
     jumping = true; 
     jumpingReachedApex = false; 
     lastJumpTime = Time.time; 
     //lastJumpStartHeight = transform.position.y; 
     lastJumpButtonTime = -10; 

     _characterState = CharacterState.Jumping; 
    } 
    void Update() 
    { 

     if (!isControllable) 
     { 
      // kill all inputs if not controllable. 
      Input.ResetInputAxes(); 
     } 

     if (Input.GetButtonDown("Jump")) 
     { 
      lastJumpButtonTime = Time.time; 
     } 

     UpdateSmoothedMovementDirection(); 

     // Apply gravity 
     // - extra power jump modifies gravity 
     // - controlledDescent mode modifies gravity 
     ApplyGravity(); 

     // Apply jumping logic 
     ApplyJumping(); 

     // Calculate actual motion 
     Vector3 movement = moveDirection * moveSpeed + new Vector3(0, verticalSpeed, 0) + inAirVelocity; 
     movement *= Time.deltaTime; 

     // Move the controller 
     CharacterController controller = GetComponent<CharacterController>(); 
     collisionFlags = controller.Move(movement); 

     // ANIMATION sector 
     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.1f) 
       { 
        _animation.CrossFade(idleAnimation.name); 
       } 
       else 
       { 
        if (_characterState == CharacterState.Running) 
        { 
         _animation[runAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0f, runMaxAnimationSpeed); 
         _animation.CrossFade(runAnimation.name); 
        } 
        else if (_characterState == CharacterState.Trotting) 
        { 
         _animation[walkAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0f, trotMaxAnimationSpeed); 
         _animation.CrossFade(walkAnimation.name); 
        } 
        else if (_characterState == CharacterState.Walking) 
        { 
         _animation[walkAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0f, walkMaxAnimationSpeed); 
         _animation.CrossFade(walkAnimation.name); 
        } 

       } 
      } 
     } 
     // ANIMATION sector 

     // Set rotation to the move direction 
     if (IsGrounded()) 
     { 

      transform.rotation = Quaternion.LookRotation(moveDirection); 

     } 
     else 
     { 
      Vector3 xzMove = movement; 
      xzMove.y = 0; 
      if (xzMove.sqrMagnitude > 0.001f) 
      { 
       transform.rotation = Quaternion.LookRotation(xzMove); 
      } 
     } 

     // We are in jump mode but just became grounded 
     if (IsGrounded()) 
     { 
      lastGroundedTime = Time.time; 
      inAirVelocity = Vector3.zero; 
      if (jumping) 
      { 
       jumping = false; 
       SendMessage("DidLand", SendMessageOptions.DontRequireReceiver); 
      } 
     } 
    } 
    void OnControllerColliderHit(ControllerColliderHit hit) 
    { 
     // Debug.DrawRay(hit.point, hit.normal); 
     if (hit.moveDirection.y > 0.01f) 
      return; 
    } 
    float GetSpeed() 
    { 
     return moveSpeed; 
    } 

    public bool IsJumping() 
    { 
     return jumping; 
    } 

    bool IsGrounded() 
    { 
     return (collisionFlags & CollisionFlags.CollidedBelow) != 0; 
    } 

    Vector3 GetDirection() 
    { 
     return moveDirection; 
    } 

    public bool IsMovingBackwards() 
    { 
     return movingBack; 
    } 

    public float GetLockCameraTimer() 
    { 
     return lockCameraTimer; 
    } 

    bool IsMoving() 
    { 
     return Mathf.Abs(Input.GetAxisRaw("Vertical")) + Mathf.Abs(Input.GetAxisRaw("Horizontal")) > 0.5f; 
    } 

    bool HasJumpReachedApex() 
    { 
     return jumpingReachedApex; 
    } 

    bool IsGroundedWithTimeout() 
    { 
     return lastGroundedTime + groundedTimeout > Time.time; 
    } 

    void Reset() 
    { 
     gameObject.tag = "Player"; 
    } 

} 

回答

0

有更新()的手柄轉動下兩行:

transform.rotation = Quaternion.LookRotation(moveDirection); 

transform.rotation = Quaternion.LookRotation(xzMove); 

按照變量moveDirection和xzMove看這些值如何確定。它應該非常簡單。提示:位於函數UpdateSmoothedMovementDirection()中的moveDirection。 moveDirection也用於使用移動來計算xzMove。剩下的我留給你。

編輯:實際處理移動的代碼段位於UpdateSmoothedMovementDirection()內部。往下看if(接地) - > if(targetDirection!= Vector3.zero)。這是處理移動的區域。這是if(targetDirection < walkSpeed * 0.9f & &接地),其中運動以90度捕捉。這是預期的功能。

我用else語句中的代碼替換掉了代碼,並且在較慢的速度下,頭像更自然地移動。當橫向和縱向都同時切換時,頭像只會以45度行走。換句話說,按向上+向左或向下+向右等

如果您不想快速行爲,只需使用else語句中的代碼並刪除條件語句。那麼你的頭像將會一直順利轉換。

+0

嗨memebrain感謝的對你有所幫助 實際上是從的Vector3(私人的Vector3 moveDirection = Vector3.zero;)確定movedirection值。我能不能得到你mean.Here我重視我的源代碼的鏈接 = ======== https://[email protected]/3rdperson/3rd.git ========= 如果您是免費的,請您檢查一下。 –

+0

我在審覈完您的項目後編輯了我的回覆。除了我在那裏討論的任何內容之外,可能都需要編寫一個自定義腳本。 我只想說明你的項目已經過時。我正在運行5.5,這也是過時的,但只是最近。我必須禁用hud.cs才能使您的項目正常工作。另外,我想指出Mechanim在管理動畫和角色控制方面做得更好。你可能會做一些教程。它會爲你提供更好的結果。 – memBrain

+0

嗨,memBrain謝謝你的支持。這個問題已經解決了,但它並不是每次45度轉彎時有時會轉向60度。在這方面你能幫助我嗎? –