Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.InputSystem;

using UnityEngine.InputSystem.Controls;


    [System.Serializable]

    public class CameraPositions

    {

        public Vector3 position;

        public Vector2 rotation;

        public float distance;

    }

    public class CameraOrbitController : MonoBehaviour

    {

        public Transform target;

        public Transform defaultTarget;

        public Vector3 targetOffset;

        public float distance = 5.0f;

        public float maxDistance = 20;

        public float minDistance = .6f;

        public float xSpeed = 5.0f;

        public float ySpeed = 5.0f;

        public int yMinLimit = -80;

        public int yMaxLimit = 80;

        public float zoomRate = 10.0f;

        public float touchZoomRate = 10.0f;

        public float panSpeed = 0.3f;

        public float zoomDampening = 5.0f;

        public float rotationDampening = 5.0f;

        [SerializeField]

        private float xDeg = 0.0f;

        [SerializeField]

        private float yDeg = 0.0f;

        private float currentDistance;

        private float desiredDistance;

        private Quaternion currentRotation;

        private Quaternion desiredRotation;

        private Quaternion rotation;

        private Vector3 position;

        private Vector3 FirstPosition;

        private Vector3 delta;

        private Vector3 lastOffset;

        public List<CameraPositions> cameraPositions;

        private Touchscreen screen;

        public PlatformDetector platformScript;

        void Start() { Init(); }

        void OnEnable() { Init(); }

        bool isEnabled = true;

        public void Init()

        {

            if (!target)

            {

                GameObject go = new GameObject("OrbitCamTarget");

                go.transform.position = Vector3.zero+new Vector3(0,1,0);

                target = go.transform;

            }

            distance = Vector3.Distance(transform.position, target.position);

            currentDistance = distance;

            desiredDistance = distance;

            position = transform.position;

            rotation = transform.rotation;

            currentRotation = transform.rotation;

            desiredRotation = transform.rotation;

            xDeg = Vector3.Angle(Vector3.right, transform.right);

            yDeg = Vector3.Angle(Vector3.up, transform.up);

            screen = Touchscreen.current;

            RestPosition();

        }

        public void ChangeCamPosition(int index)

        {

            UpdateConfig(cameraPositions[index].position, cameraPositions[index].rotation.y, cameraPositions[index].rotation.x, cameraPositions[index].distance);

        }

        public void RestPosition()

        {

            target = defaultTarget;

            UpdateConfig(cameraPositions[0].position, cameraPositions[0].rotation.y, cameraPositions[0].rotation.x, cameraPositions[0].distance);

        }

        void LateUpdate()

        {

  

            if (!Application.isEditor && isEnabled && platformScript.isTouch)

            {

                List<TouchControl> touches = ActiveTouches(screen);

                // Debug.Log("touches: " + touches.Count.ToString());

                //ZOOM & PAN

                if (touches.Count == 2)

                {

                    TouchControl touchZero = touches[0];

                    TouchControl touchOne = touches[1];

                    //ZOOM

                    Vector2 touchZeroPreviousPosition = touchZero.position.ReadValue() - touchZero.delta.ReadValue();

                    Vector2 touchOnePreviousPosition = touchOne.position.ReadValue() - touchOne.delta.ReadValue();

                    float prevTouchDeltaMag = (touchZeroPreviousPosition - touchOnePreviousPosition).magnitude;

                    float TouchDeltaMag = (touchZero.position.ReadValue() - touchOne.position.ReadValue()).magnitude;

                    float deltaMagDiff = prevTouchDeltaMag - TouchDeltaMag;

                    desiredDistance += deltaMagDiff * Time.deltaTime * touchZoomRate * 0.0025f * Mathf.Abs(desiredDistance);

                    Vector2 previousPositionMiddle = (touchZeroPreviousPosition + touchOnePreviousPosition) / 2;

                    Vector2 currentPositionMiddle = (touchZero.position.ReadValue() + touchOne.position.ReadValue()) / 2;

                    Vector2 middlePositionDelta = currentPositionMiddle - previousPositionMiddle;

                    lastOffset = targetOffset;

                    float speedMulti = 0.003f * panSpeed * currentDistance;

                    //move targetoffset on the XZ plane according to the delta

                    targetOffset = lastOffset + transform.right * middlePositionDelta.x * speedMulti +  transform.up * middlePositionDelta.y * speedMulti;

                }

                //ORBIT

                if (touches.Count == 1 && touches[0].phase.ReadValue() == UnityEngine.InputSystem.TouchPhase.Moved)

                {

                    Vector2 touchposition = touches[0].delta.ReadValue();

                    xDeg += touchposition.x * xSpeed * 0.03f;

                    yDeg -= touchposition.y * ySpeed * 0.03f;

                    yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit);

                }

            }

            desiredRotation = Quaternion.Euler(yDeg, xDeg, 0);

            currentRotation = transform.rotation;

            rotation = Quaternion.Lerp(currentRotation, desiredRotation, Time.deltaTime * rotationDampening);

            transform.rotation = rotation;

#if UNITY_STANDALONE || UNITY_WEBGL || UNITY_EDITOR

            if (isEnabled && !platformScript.isTouch)

            {

                //Mouse Rotate

                if (Mouse.current.leftButton.isPressed)

                {

                    FirstPosition = Mouse.current.delta.ReadValue();

                    xDeg += FirstPosition.x * xSpeed * 0.03f;

                    yDeg -= FirstPosition.y * ySpeed * 0.03f;

                    yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit);

                }

               

                //Mouse Pan

                if (Mouse.current.rightButton.isPressed)

                {

                    delta = Mouse.current.delta.ReadValue();

                    targetOffset += lastOffset + transform.right * delta.x * 0.003f * panSpeed * currentDistance + transform.up * delta.y * 0.003f * panSpeed * currentDistance;

                }

            }

            //Debug.Log(Mouse.current.scroll.magnitude);

            //Mouse Zoom

            if (Mouse.current.scroll.magnitude>0)

            {

                Vector2 scrollValue = Mouse.current.scroll.ReadValue();

                Debug.Log($"Scroll value: {scrollValue}");

                

                desiredDistance += Mouse.current.scroll.ReadValue().normalized.y * -zoomRate*Time.deltaTime;

            }

#endif

            desiredDistance = Mathf.Clamp(desiredDistance, minDistance, maxDistance);

            currentDistance = Mathf.Lerp(currentDistance, desiredDistance, Time.deltaTime * zoomDampening);

            position = target.position - (rotation * Vector3.forward * currentDistance);

            position = position - targetOffset;

            transform.position = position;

        }

        private static float ClampAngle(float angle, float min, float max)

        {

            if (angle < -360)

                angle += 360;

            if (angle > 360)

                angle -= 360;

            return Mathf.Clamp(angle, min, max);

        }

        private List<TouchControl> ActiveTouches(Touchscreen screen)

        {

            List<TouchControl> i = new List<TouchControl>();

            foreach (var item in screen.touches)

            {

                if (item.isInProgress)

                    i.Add(item);

            }

            return i;

        }

        public void UpdateConfig(Vector3 _targetOffset,float _xDeg,float _yDeg,float _desiredZoomLevel)

        {

            xDeg = _xDeg;

            yDeg = _yDeg;

            desiredDistance = _desiredZoomLevel;

            targetOffset = _targetOffset;

        }

        public void InteractionBlock(bool _state)

        {

            isEnabled = !_state;

            Debug.Log("State Updated");

        }

    }