void Update() { motor.MovementInput = Vector3.zero; bool forwardKeyDown = Input.GetKey(forwardKey); bool backwardKeyDown = Input.GetKey(backwardKey); bool leftKeyDown = Input.GetKey(leftKey); bool rightKeyDown = Input.GetKey(rightKey); bool jumpKeyPressed = Input.GetKeyDown(jumpKey); bool walkKeyDown = Input.GetKey(walkToggle); bool mouseLookDown = Input.GetMouseButton((int)mouseLookButton) && enableMouseLook; bool mouseLookPressed = Input.GetMouseButtonDown((int)mouseLookButton) && enableMouseLook; bool bothMiceDown = Input.GetMouseButton((int)mouseRunAndLookButton) && mouseLookDown && enableRunAndLook; bool autorunPressed = Input.GetMouseButtonDown((int)autorunToggleButton); IsRunning = !walkKeyDown; MouseLook = mouseLookDown; if (autorunPressed) { autorun = !autorun; } if (autorun || forwardKeyDown || bothMiceDown) { motor.MovementInput.z += 1f; } if (backwardKeyDown) { motor.MovementInput.z -= 1f; } if (mouseLookDown) { if (leftKeyDown) { motor.MovementInput.x -= 1f; } if (rightKeyDown) { motor.MovementInput.x += 1f; } } else { if (leftKeyDown) { motor.Yaw(-(Time.smoothDeltaTime * keyTurnSpeed)); } if (rightKeyDown) { motor.Yaw(Time.smoothDeltaTime * keyTurnSpeed); } } // Set movement speed if (motor.MovementInput.z < 0) { motor.MovementSpeed = walkKeyDown ? backwardWalkSpeed : backwardRunSpeed; } else { motor.MovementSpeed = walkKeyDown ? forwardWalkSpeed : forwardRunSpeed; } // Jump if (jumpKeyPressed) { motor.Jump(); } // Clear autorun if ((mouseLookDown && (leftKeyDown || rightKeyDown)) || forwardKeyDown || backwardKeyDown || bothMiceDown) { autorun = false; } // If we're moving, rotate camera behind us if (motor.MovementInput != Vector3.zero) { RPGCamera.Instance.RotateCameraBehindTarget = cameraRotateBehindOnMove; } // If we're holding down mouse look, lock camera if (mouseLookDown) { RPGCamera.Instance.LockCameraBehindTarget = cameraLockBehindOnMouseLook; motor.Yaw(Input.GetAxisRaw("Mouse X") * Time.smoothDeltaTime * mouseTurnSpeed); } // If we pressed mouse look, set rotation if (mouseLookPressed) { Camera cam = RPGCamera.Instance.Camera; motor.SetYaw(RPGInputUtils.SignedAngle(Vector3.forward, cam.transform.forward, Vector3.up)); } }
void LateUpdate() { Instance = this; if (!HasCamera) { Debug.LogError("No camera found"); return; } if (!HasTarget) { Debug.LogError("No target found"); return; } bool rotate = RPGInputUtils.GetButtonSafe(MouseRotateButton, false); bool mouseLook = RPGInputUtils.GetButtonSafe(MouseLookButton, false); bool smoothRotation = SmoothRotation || SmoothAutoRotation; float smoothRotationSpeed = SmoothRotationSpeed; // This defines our "real" distance to the player realDistance -= RPGInputUtils.GetAxisRawSafe(ZoomAxis, 0f) * ZoomSpeed; realDistance = Mathf.Clamp(realDistance, MinDistance, MaxDistance); // This is the distance we want to (clamped to what is viewable) targetDistance = realDistance; targetDistance = Mathf.Clamp(targetDistance, currentMinDistance, currentMaxDistance); // This is our current distance if (SmoothZoom) { currentDistance = Mathf.Lerp(currentDistance, targetDistance, Time.deltaTime * SmoothZoomSpeed); } else { currentDistance = targetDistance; } // Calculate offset vector Vector3 offset = new Vector3(0, 0, -currentDistance); // LMB is not down, but we should rotate camera behind target if (!rotate && RotateCameraBehindTarget) { targetYaw = RPGInputUtils.SignedAngle(offset.normalized, -Target.forward, Vector3.up); smoothRotation = SmoothAutoRotation; smoothRotationSpeed = SmoothAutoRotationSpeed; } // Only LMB down and no lock if (rotate && !mouseLook && !LockCameraBehindTarget) { targetYaw += (RPGInputUtils.GetAxisRawSafe(YawAxis, 0f) * RotationMouseSpeed); targetPitch -= (RPGInputUtils.GetAxisRawSafe(PitchAxis, 0f) * RotationMouseSpeed); targetPitch = Mathf.Clamp(targetPitch, MinPitch, MaxPitch); smoothRotation = SmoothRotation; smoothRotationSpeed = SmoothRotationSpeed; } // RMB if (mouseLook && LockCameraBehindTarget) { targetPitch -= (RPGInputUtils.GetAxisRawSafe(PitchAxis, 0f) * RotationMouseSpeed); targetPitch = Mathf.Clamp(targetPitch, MinPitch, MaxPitch); } // Lock camera behind target, this overrides everything if (LockCameraBehindTarget) { targetYaw = RPGInputUtils.SignedAngle(offset.normalized, -Target.transform.forward, Vector3.up); smoothRotation = false; } // Clamp targetYaw to -180, 180 targetYaw = Mathf.Repeat(targetYaw + 180f, 360f) - 180f; if (!smoothRotation) { currentYaw = targetYaw; currentPitch = targetPitch; } else { // Clamp smooth currentYaw to targetYaw and clamp it to -180, 180 currentYaw = Mathf.LerpAngle(currentYaw, targetYaw, Time.deltaTime * smoothRotationSpeed); currentYaw = Mathf.Repeat(currentYaw + 180f, 360f) - 180f; // Smooth pitch currentPitch = Mathf.LerpAngle(currentPitch, targetPitch, Time.deltaTime * smoothRotationSpeed); } // Rotate offset vector offset = Quaternion.Euler(currentPitch, currentYaw, 0f) * offset; // Position camera holder correctly transform.position = TargetPosition + offset; // And then have the camera look at our target Camera.transform.LookAt(TargetPosition); // Make sure we don't collide with anything float closest = float.MaxValue; bool mid = AvoidCollision(transform.position, ref closest); bool bottomLeft = AvoidCollision(Camera.ScreenToWorldPoint(new Vector3(0, 0, Camera.nearClipPlane)), ref closest); bool bottomRight = AvoidCollision(Camera.ScreenToWorldPoint(new Vector3(0, Screen.height, Camera.nearClipPlane)), ref closest); bool topLeft = AvoidCollision(Camera.ScreenToWorldPoint(new Vector3(Screen.width, 0, Camera.nearClipPlane)), ref closest); bool topRight = AvoidCollision(Camera.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, Camera.nearClipPlane)), ref closest); if (mid && bottomLeft && bottomRight && topLeft && topRight) { currentMinDistance = MinDistance; currentMaxDistance = MaxDistance; } else { currentMinDistance = Mathf.Min(currentMinDistance, 1f); currentMaxDistance = Mathf.Max(currentMinDistance + 0.05f, closest * 0.9f); } // Clear this flag LockCameraBehindTarget = false; RotateCameraBehindTarget = false; }