旋转摄像机

using System;
using UnityEngine;
namespace MainEditor
{
    /// <summary>
    /// 爱的魔力转圈圈
    /// 旋转摄像机指定度数
    /// </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)// 右
                        sign = 1;
                    else if(newValue >250)// 左
                        sign = -1;
                }
                else
                {
                    if(newValue >oldValue)//右
                        sign = 1;
                    else if(newValue < oldValue)//左
                        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;
                // 固定的角度选份量的中间,避免稍微向左偏移就切换到其他角度
                eulerAngle = new Vector3(0, 0, v * stopAnale + stopAnale * 0.5f);
                runState = 1;
            }
            else
            {
                // power 是为了压制或者放大旋转距离。如果半径过小速度过大会飞快旋转
                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 ;
            // 求2点间的弧度值
            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));
            // 因为更新了旋转,所以需要重新获取坐标
            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);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小鱼游戏开发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值