当前位置:网站首页>Rotating camera

Rotating camera

2022-06-13 00:50:00 Small fish game development

using System;
using UnityEngine;
namespace MainEditor
{
    
    /// <summary>
    ///  The magic of love goes around 
    ///  Rotate the camera by a specified number of degrees 
    /// </summary>
    public class RotationCamera : MonoBehaviour
    {
    
        public int weight = 8;
        public float radius = 10;
        public float power = 0.05f;
        public int count=8;
        public Action<int> onIndexChanged;

        int curAngleIndex;
        int curIndex;
        int runState;
        int stopAnale;
        float perimeter;
        Vector2 speed;
        Vector2 worldPos;
        Vector2 origin;
        Vector2 direction;
        Vector2 screenPos;
        Vector3 eulerAngle;
        Action[] inputFunctions;
        Action[] runStateFunctions;

        private void Awake()
        {
    
            gameObject.AddComponent<DrawRadius>().radius = radius;

            stopAnale = 360 / weight;
            origin = transform.position;
            perimeter = 2 * Mathf.PI * radius;

            inputFunctions = new Action[] {
     Default, MouseDown, MouseStay, MouseUp };
            runStateFunctions = new Action[] {
     SpeedRoation, FixedAngle };

            onIndexChanged = index => Debug.Log(index);
        }
        private void Update()
        {
    
            inputFunctions[GetInputState()].Invoke();
        }

        void Default()
        {
    
            if (runState == -1)
                return;

            runStateFunctions[runState].Invoke();
        }

        void Rotation(Vector3 vector )
        {
    
            var newValue = vector.z;
            var oldValue = transform.localEulerAngles.z;
            if (Mathf.Abs(newValue - oldValue) < 0.0001f)
                return;
            transform.localEulerAngles = vector;
            if (newValue > 359)
                return;
            var v = (int)vector.z / stopAnale;
            if (v != curAngleIndex)
            {
    
                curAngleIndex = v;
                // 0 - 359
                int sign = 0;
                if(Mathf.Abs(newValue - oldValue) >250)
                {
    
                    if(newValue<100)//  Right 
                        sign = 1;
                    else if(newValue >250)//  Left 
                        sign = -1;
                }
                else
                {
    
                    if(newValue >oldValue)// Right 
                        sign = 1;
                    else if(newValue < oldValue)// Left 
                        sign = -1;
                }
                curIndex += sign;
                if (curIndex < 0)
                    curIndex = count - 1;
                else if (curIndex >= count)
                    curIndex = 0;

                onIndexChanged?.Invoke(curIndex);
            }
        }

        void SpeedRoation()
        {
    
            speed *= Mathf.Pow(0.1f, Time.deltaTime);
            if (Mathf.Abs(speed.magnitude) < 10)
            {
    
                speed = Vector3.zero;
                var angle = transform.localEulerAngles.z;
                var v = (int)angle / stopAnale;
                //  Choose the middle of the portion at a fixed angle , Avoid switching to other angles with a slight shift to the left 
                eulerAngle = new Vector3(0, 0, v * stopAnale + stopAnale * 0.5f);
                runState = 1;
            }
            else
            {
    
                // power  To suppress or enlarge the rotation distance . If the radius is too small and the speed is too fast 
                var radian = speed.magnitude * power / perimeter;
                var angle = Mathf.Rad2Deg * radian;
                Rotation(transform.localEulerAngles + new Vector3(0, 0, angle * Mathf.Sign(direction.x)));
            }
        }

        void FixedAngle()
        {
    
            Rotation(Vector3.Slerp(transform.localEulerAngles, eulerAngle, 0.1f));
            if (Mathf.Abs(transform.localEulerAngles.z - eulerAngle.z) < 0.1f)
            {
    
                Rotation(eulerAngle);
                runState = -1;
            }
        }

        void MouseDown()
        {
    
            runState = -1;
            worldPos = GetWorldPosition();
            screenPos = Input.mousePosition;
        }

        void MouseUp()
        {
    
            Vector2 pos = GetWorldPosition();
            var delta = worldPos - pos;
            direction = ((Vector2)Input.mousePosition - screenPos).normalized;
            speed = delta / Time.deltaTime;
            worldPos = pos;
            runState = 0;
        }

        void MouseStay()
        {
    
            Vector2 pos = GetWorldPosition();
            var oldDir = (worldPos - origin).normalized * radius ;
            var newDir = (pos - origin).normalized * radius ;
            //  seek 2 Radian value between points 
            var radian = Mathf.Atan2(newDir.y, newDir.x) - Mathf.Atan2(oldDir.y, oldDir.x);
            var angle = Mathf.Rad2Deg * radian;
            Rotation(transform.localEulerAngles + new Vector3(0, 0, -angle));
            //  Because the rotation is updated , So we need to get the coordinates again 
            worldPos = GetWorldPosition();
        }

        int GetInputState()
        {
    
            if (Input.GetMouseButtonDown(0))
                return 1;
            if (Input.GetMouseButton(0))
                return 2;
            if (Input.GetMouseButtonUp(0))
                return 3;
            return 0;
        }

        Vector3 GetWorldPosition()
        {
    
            return Camera.main.ScreenToWorldPoint(Input.mousePosition);
        }
    }
}
原网站

版权声明
本文为[Small fish game development]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202280557591853.html