예제 #1
0
    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));
        }
    }
예제 #2
0
    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;
    }