3D轮转图

今天介绍3D轮转图的制作,上边这个效果实在3D轮转图的基础上做成了曲面屏展示。

制作轮转图通俗来说就是以一个点为中心点,生成Cube围绕他进行对应的公转和自转。

 首先需要定义半径r和数量num。之后求出他的角度。(2*mathf.pi 为360度)

public int num;

public float r;
float ang ;
ang = 2 * Mathf.PI / num;

在之后我封装了一个方法来计算位置,同时,生成对应数量的Cube。

public void Move()
{
    for (int i = 0; i < num; i++)
    {
        float x = Mathf.Sin(i * ang + allAng) * r;
        float z = Mathf.Cos(i * ang + allAng) * r;
        if(list.Count <= i)
        {
            GameObject sphere = Instantiate(prefab);
            sphere.transform.parent = transform;
            sphere.GetComponent<CyclogramItem>().cyclogram = this;
            sphere.GetComponent<MeshRenderer>().material.mainTexture = textures[i];
            list.Add(sphere);
            sortList.Add(sphere.transform);
            sphere.name = i+"";
        }
        list[i].transform.localPosition = new Vector3(x, 0, z);
        //当前的弧度转换为度
        list[i].transform.localEulerAngles = Vector3.up * ((i * ang + allAng) * Mathf.Rad2Deg);

    }
}

在上述代码中提到了两个集合,如下。这两个集合是用来存储生成的预制体 GameObject 类型和Transform类型。 list是方便记录数据,而sortlist 见名知意是用来排序。那么哪里需要用到排序呢?

 List<GameObject> list = new List<GameObject>();
 List<Transform> sortList = new List<Transform>();

当我们在用鼠标拖拽其中的一个Cube时,生成的预制体集合会跟随这个拖拽动作进行一个公转的状态,而我们的sortlist在此处就有了用处。当公转的状态停止时,他会有一个具体相机最近的GameObject ,相当于就是我们抽奖选中的物品。类似这样的一个效果。那么我们只需要给list集合里面所有GameObject的Transform,position.z做一个排序就好了。要拿到距离相机最近,就相当于他的z是最小的。那么整体逻辑知道后,我们看看代码是怎么实现的。代码中的DT等同于我们的Dotween插件。

public void Inertia(float dis)
{
    float time =Mathf.Abs(  dis / dec);
    DT.To((a) =>
    {
        OnDrag(a);
    }, dis, 0, time).OnComplete(() =>
    {
        sortList.Sort((a, b) =>
        {
            if (a.position.z < b.position.z)
            {
                return -1;
            }
            else if (a.position.z == b.position.z)
            {
                return 0;
            }
            else
            {
                return 1;
            }
        });
        float aligning = Mathf.Asin(sortList[0].localPosition.x / r);
        float aligntimer = Mathf.Abs( aligning * r / 200);
        DT.To((a) =>
        {
            allAng = a;
            Move();
        }, allAng, allAng + aligning, aligntimer).OnComplete(() =>
        {
            int index = int.Parse(sortList[0].name);
            if(index<8)
            {
                print(index + 8);
                img.sprite = Resources.Load<Sprite>("character_"+ (index + 8));
            }
            else
            {
                print(index - 8);
                img.sprite = Resources.Load<Sprite>("character_" + (index - 8));
            }
           
        });
    });
}

现在我们需要考虑拖拽的触发,这块直接上代码。只需要拿到物体的屏幕坐标,同时将他的屏幕坐标的z值,和鼠标位置的x和y值记录,将这个x和物体的x做差值,拿到物体移动的距离就好了。之后代用我们上边写好的Move()方法就可以让他进行旋转了。

private void OnMouseDrag()
{
    Vector3 pos = Camera.main.WorldToScreenPoint(transform.position);
    Vector3 next = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, pos.z));
    float dis = next.x - transform.position.x;
    cyclogram.OnDrag(dis);
}

现在将两个脚本代码进行展示

Cyclogram 脚本需要挂在一个空对象下面

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;

public class Cyclogram : MonoBehaviour
{
    public Image img;

    public Texture[] textures;

    public GameObject prefab;

    public int num;

    public float r;
    float ang ;
    public float dec = 5f;
    List<GameObject> list = new List<GameObject>();
    List<Transform> sortList = new List<Transform>();
    // Start is called before the first frame update
    void Start()
    {
        ang = 2 * Mathf.PI / num;
        Move();
        img.sprite = Resources.Load<Sprite>("character_0");
    }

    float allAng = 0;
    public void OnDrag(float dis)
    {
        float moveang = dis / r;
        allAng -= moveang;
        Move();
    }

    public void Move()
    {
        for (int i = 0; i < num; i++)
        {
            float x = Mathf.Sin(i * ang + allAng) * r;
            float z = Mathf.Cos(i * ang + allAng) * r;
            if(list.Count <= i)
            {
                GameObject sphere = Instantiate(prefab);
                sphere.transform.parent = transform;
                sphere.GetComponent<CyclogramItem>().cyclogram = this;
                sphere.GetComponent<MeshRenderer>().material.mainTexture = textures[i];
                list.Add(sphere);
                sortList.Add(sphere.transform);
                sphere.name = i+"";
            }
            list[i].transform.localPosition = new Vector3(x, 0, z);
            //当前的弧度转换为度
            list[i].transform.localEulerAngles = Vector3.up * ((i * ang + allAng) * Mathf.Rad2Deg);

        }
    }

    public void Inertia(float dis)
    {
        float time =Mathf.Abs(  dis / dec);
        DT.To((a) =>
        {
            OnDrag(a);
        }, dis, 0, time).OnComplete(() =>
        {
            sortList.Sort((a, b) =>
            {
                if (a.position.z < b.position.z)
                {
                    return -1;
                }
                else if (a.position.z == b.position.z)
                {
                    return 0;
                }
                else
                {
                    return 1;
                }
            });
            float aligning = Mathf.Asin(sortList[0].localPosition.x / r);
            float aligntimer = Mathf.Abs( aligning * r / 200);
            DT.To((a) =>
            {
                allAng = a;
                Move();
            }, allAng, allAng + aligning, aligntimer).OnComplete(() =>
            {
                int index = int.Parse(sortList[0].name);
                if(index<8)
                {
                    print(index + 8);
                    img.sprite = Resources.Load<Sprite>("character_"+ (index + 8));
                }
                else
                {
                    print(index - 8);
                    img.sprite = Resources.Load<Sprite>("character_" + (index - 8));
                }
               
            });
        });
    }
    // Update is called once per frame
    void Update()
    {
        
    }
}

CyclogramItem 需要给预制体添加

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

public class CyclogramItem : MonoBehaviour
{
    public Cyclogram cyclogram;
    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }

    private void OnMouseDrag()
    {
        Vector3 pos = Camera.main.WorldToScreenPoint(transform.position);
        Vector3 next = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, pos.z));
        float dis = next.x - transform.position.x;
        cyclogram.OnDrag(dis);
    }

    private void OnMouseUp()
    {
        Vector3 pos = Camera.main.WorldToScreenPoint(transform.position);
        Vector3 next = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, pos.z));
        float dis = next.x - transform.position.x;
        cyclogram.Inertia(dis);

    }
}

将轮转图的大体思路讲完之后,我们看看怎么去绘制曲面

这块我们需要将15张图片拼接成一个圆环,那么每张图片也是一个弧形状态。所以我们需要定义数量num ,半径r ,然后求出他的周长和半径。

 float n = 15; //个数
 float l; //周长
 float r; //半径

 拿到周长和半径方便求出整体的角度和每个图片的弧度。

l = 150 * n;
r = l / (2 * Mathf.PI);
float ang = 2 * Mathf.PI / n;
float sunang = 2 * Mathf.PI / (n * 10);

现在我们开始进行绘制这个圆环。这块同之前的绘制方式,不再过多叙述。

 VertexHelper vh = new VertexHelper();
 for (int i = -5; i <= 5; i++)
 {
     float x = Mathf.Sin(i * sunang) * r - Mathf.Sin(0) * r;
     float z = Mathf.Cos(i * sunang) * r - Mathf.Cos(0) * r;
     float y = 113;
     float y0 = -113;

     float uvx = (float)(i + 5) / 10;
     vh.AddVert(new Vector3(x, y, z), Color.white, new Vector2(uvx, 1));
     vh.AddVert(new Vector3(x, y0, z), Color.white, new Vector2(uvx, 0));

     if (i < 5)
     {
         int j = i + 5;
         vh.AddTriangle(j * 2 + 1, j * 2, (j + 1) * 2);
         vh.AddTriangle(j * 2 + 1, (j + 1) * 2, (j + 1) * 2 + 1);
     }
 }

最后还差一步Mesh赋值。整体代码如下:

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

public class CreateCamber : MonoBehaviour
{
    float n = 15; //个数
    float l; //周长
    float r; //半径
    // Start is called before the first frame update
    void Start()
    {
        l = 150 * n;
        r = l / (2 * Mathf.PI);
        float ang = 2 * Mathf.PI / n;
        float sunang = 2 * Mathf.PI / (n * 10);

        VertexHelper vh = new VertexHelper();
        for (int i = -5; i <= 5; i++)
        {
            float x = Mathf.Sin(i * sunang) * r - Mathf.Sin(0) * r;
            float z = Mathf.Cos(i * sunang) * r - Mathf.Cos(0) * r;
            float y = 113;
            float y0 = -113;

            float uvx = (float)(i + 5) / 10;
            vh.AddVert(new Vector3(x, y, z), Color.white, new Vector2(uvx, 1));
            vh.AddVert(new Vector3(x, y0, z), Color.white, new Vector2(uvx, 0));

            if (i < 5)
            {
                int j = i + 5;
                vh.AddTriangle(j * 2 + 1, j * 2, (j + 1) * 2);
                vh.AddTriangle(j * 2 + 1, (j + 1) * 2, (j + 1) * 2 + 1);
            }
        }

        Mesh mesh = new Mesh();
        vh.FillMesh(mesh);

        GetComponent<MeshFilter>().mesh = mesh;
        GetComponent<MeshCollider>().sharedMesh = mesh;
       // transform.LookAt(transform.parent.transform);
    }

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
HTML和CSS可以通过使用CSS3的transform属性来实现3D轮转。下面是一个简单的实现步骤: 1. 首先,在HTML文件中创建一个容器元素,用于包裹轮转的所有元素。例如: ```html <div class="container"> <!-- 定义每个像的元素 --> <div class="image"></div> <div class="image"></div> <div class="image"></div> <!-- 可添加更多像元素 --> </div> ``` 2. 接下来,在CSS文件中设置容器元素和像元素的样式。首先,设置容器元素的样式,使其能够显示出3D效果: ```css .container { width: 300px; /* 设置容器宽度 */ height: 300px; /* 设置容器高度 */ perspective: 1000px; /* 设置透视效果,值越大离观察者越远 */ } ``` 3. 然后,设置像元素的样式,并应用3D效果: ```css .image { width: 100%; /* 设置像元素宽度 */ height: 100%; /* 设置像元素高度 */ background-image: url("路径/到/像"); /* 设置像背景 */ background-size: cover; /* 设置像背景大小,以覆盖整个像元素 */ transform-style: preserve-3d; /* 保持3D效果 */ animation: rotation 10s infinite linear; /* 设置像旋转动画,时间、循环方式可根据需求自行调整 */ } @keyframes rotation { from { transform: rotateY(0deg); /* 开始时的旋转角度 */ } to { transform: rotateY(360deg); /* 结束时的旋转角度 */ } } ``` 通过以上步骤,我们就可以实现一个简单的3D轮转。你可以根据需要调整容器元素和像元素的样式,添加更多的像元素来实现更复杂的效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值