绘制3D轮转图和手写DoTween

轮转图在游戏中有着非常广泛的应用,它可以以一种炫酷的形式将图片,人物等展示出来,可以给人耳目一新的感觉。同时,它也是游戏开发中不可或缺的一个重要项目。

今天,我们大家就一起来学习一下3D轮转图的绘制

轮转图的绘制原理其实是很容易理解的,

我们利用父物体生成子物体,子物体利用x轴上的间距和 最中心靠前的物体显示的最大(也就是缩放最大),两侧物体逐渐变小(缩放逐渐变小)的原理制造视觉差,从而让我们感受到3D效果,之后利用拖拽事件等使其可以拖动旋转

 

下面是我们的绘制代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RotationChart : MonoBehaviour
{
    public int n;
    public float spacing = 1;
    float r;
    float c;
    float ang;
    float distance = 0;
    List<GameObject> list = new List<GameObject>();
    List<Transform> sortList = new List<Transform>();
    // Start is called before the first frame update
    void Start()
    {
        c = (1 + spacing) * n;
        r = c / (2 * Mathf.PI);
        ang = 2 * Mathf.PI / n;
        for (int i = 0; i < n; i++)
        {
            list.Add(Instantiate(Resources.Load<GameObject>("pp"), transform));
            float x = Mathf.Sin(i * ang) * r;
            float z = Mathf.Cos(i * ang) * r;
            list[i].transform.localPosition = new Vector3(x, 0, z);
            list[i].AddComponent<PlayerMove>();
            sortList.Add(list[i].transform);
        }
    }
    public void Move(float dis)
    {
        distance -= dis / r;
        for (int i = 0; i < list.Count; i++)
        {
            float x = Mathf.Sin(i * ang + distance) * r;
            float z = Mathf.Cos(i * ang + distance) * r;
            list[i].transform.localPosition = new Vector3(x, 0, z);
        }
    }

    public void Inertia(float endspeed)
    {
        float time = Mathf.Abs(endspeed) / 3;
        Dotw.To((float a) =>
        {
            Move(a);
        },endspeed,0,time).OnComlate(()=> 
        {
            Align();                    
        });
    }

    private void Align()
    {
        sortList.Sort((a, b) =>
        {
            if (a.localPosition.z<b.localPosition.z)
            {
                return -1;
            }
            else if (a.localPosition.z == b.localPosition.z)
            {
                return 0;
            }
            else
            {
                return 1;
            }
        });
        float AlignAng = Mathf.Atan(sortList[0].localPosition.x / sortList[0].localPosition.z);
        float AlignDis = AlignAng * r;
        float time = Mathf.Abs(AlignDis) / 1;
        Dotw.To((float a) =>
        {
            for (int i = 0; i < list.Count; i++)
            {
                float x = Mathf.Sin(i * ang + a) * r;
                float z = Mathf.Cos(i * ang + a) * r;
                list[i].transform.localPosition = new Vector3(x, 0, z);
            }            
        }, distance, distance - AlignAng, time);
    }
    // Update is called once per frame
    void Update()
    {
        
    }
}

先上来是一系列的准备工作,通过简单计算获得轮转图的半径,周长,每份的弧度等数据。

然后是我们移动的方法,别的地方会调用这个移动的方法,并传过来一个参数,我们可以根据参数求出个项数据,从而确定我们预制体的新的位置。

移动完成之后我们还有惯性,惯性同样也是其他地方调用,传过来一个参数。我们通过这个参数求出从我们拖动松手到轮转图停止的时间,然后用我们的手写DoTween来实现惯性的平滑移动。

最后是我们的对齐,我们要让里我们最近的一个预制体移动到它应该在的位置,同样也是求出参数,然后同手写DoTween来实现移动。

轮转图有了移动,惯性和对齐基本上就可以满足我们的基本需求了,如果还有其他需求,可以在这个的基础上自己添加。

我们在开发功能的时候如果遇到DoTween,大部分时候是直接使用插件的,如果没有插件的情况下,我们可能需要手写DoTween,我们在这次的轮转图开发中也用到了这个,下面我们一起来看一下手写DoTween。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

public class Dotw : MonoBehaviour
{
    float starttime, nowtime, alltime;
    float now;
    Action<float> action;
    Action comlate;
    bool isplay = true;

    public static Dotw To(Action<float> action,float starttime,float nowtime,float alltime)
    {
        GameObject obj = new GameObject("Dt");
        Dotw self = obj.AddComponent<Dotw>();
        self.starttime = starttime;
        self.nowtime = nowtime;
        self.alltime = alltime;
        self.now = Time.time;
        self.action = action;
        return self;
    }
    public void OnComlate(Action comlate)
    {
        this.comlate = comlate;
    }
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if (Time.time-now<alltime)
        {
            float p = (Time.time - now) / alltime;
            float C = (1 - p) * starttime + nowtime * p;
            if (action!=null)
            {
                action(C);
            }
        }
        else if(isplay)
        {
            isplay = false;
            if (action!=null)
            {
                action(nowtime);
            }
            if (comlate!=null)
            {
                comlate();
            }
            Destroy(gameObject);
        }
    }
}

手写DoTween其实就是知道其实起始时间,结束时间,现在时间等各项参数,然后自己模拟出来物体平滑移动的效果。代码也非常的通俗易懂,大家可以参考一下上面的代码。

这些代码都只是实现了基本的功能,还有很大的不足,大家参考一下就好。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值