void LateUpdate() { // Early out if we don't have a target if (!target) { return; } //当鼠标或者手指在触摸中时 if (JFConst.TouchIng()) { bool follow = true; //计算相机与主角Y轴旋转角度的差。 float abs = Mathf.Abs(transform.rotation.eulerAngles.y - controller.transform.rotation.eulerAngles.y); //abs等于180的时候标示摄像机完全面对这主角, 》130 《 230 表示让面对的角度左右偏移50度 //这样做是不希望摄像机跟随主角,具体效果大家把代码下载下来看看,这样的摄像机效果很好。 if (abs > 130 && abs < 230) { follow = false; } else { follow = true; } float wantedRotationAngle = target.eulerAngles.y; float wantedHeight = target.position.y + height; float currentRotationAngle = transform.eulerAngles.y; float currentHeight = transform.position.y; //主角面朝射线机 和背对射线机 计算正确的位置 if (follow) { currentRotationAngle = Mathf.LerpAngle(currentRotationAngle, wantedRotationAngle, rotationDamping * Time.deltaTime); currentHeight = Mathf.Lerp(currentHeight, wantedHeight, heightDamping * Time.deltaTime); Quaternion currentRotation = Quaternion.Euler(0, currentRotationAngle, 0); Vector3 positon = target.position; positon -= currentRotation * Vector3.forward * distance; positon = new Vector3(positon.x, currentHeight, positon.z); transform.position = Vector3.Lerp(transform.position, positon, Time.time); } else { Vector3 positon = target.position; Quaternion cr = Quaternion.Euler(0, currentRotationAngle, 0); positon += cr * Vector3.back * distance; positon = new Vector3(positon.x, target.position.y + height, positon.z); transform.position = Vector3.Lerp(transform.position, positon, Time.time); } } //这里是计算射线的方向,从主角发射方向是射线机方向 Vector3 aim = target.position; //得到方向 Vector3 ve = (target.position - transform.position).normalized; float an = transform.eulerAngles.y; aim -= an * ve; //在场景视图中可以看到这条射线 Debug.DrawLine(target.position, aim, Color.red); //主角朝着这个方向发射射线 RaycastHit hit; if (Physics.Linecast(target.position, aim, out hit)) { string name = hit.collider.gameObject.tag; if (name != "MainCamera" && name != "terrain") { //当碰撞的不是摄像机也不是地形 那么直接移动摄像机的坐标 transform.position = hit.point; } } // 让射线机永远看着主角 transform.LookAt(target); }
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; if (JFConst.TouchIng()) { Vector3 vpos3 = Camera.main.WorldToScreenPoint(transform.position); Vector2 vpos2 = new Vector2(vpos3.x, vpos3.y); Vector2 input = new Vector2(Input.mousePosition.x, Input.mousePosition.y); if (Vector2.Distance(vpos2, input) > 10.0f) { Vector2 normalied = ((vpos2 - input)).normalized; targetDirection = new Vector3(normalied.x, 0.0f, normalied.y); float y = Camera.main.transform.rotation.eulerAngles.y; targetDirection = Quaternion.Euler(0f, y - 180, 0f) * targetDirection; } } // 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; } } }