IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> unity值环状图片轮播 -> 正文阅读

[游戏开发]unity值环状图片轮播

一、效果图

二、效果制作

我们在unity中用一个点作为父物体,在父物体下创建几张图片,我们旋转父物体的Z轴,就会发现子物体会围绕父物体旋转,通过这个特性,有了一个思路,创建一个围绕一个点的图片圆环,然后通过旋转父物体z轴就可以实现这个效果。好的我们先按照这个思路创建一个图片圆环?

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

/// <summary>
/// 创建圆环
/// </summary>
public class CreateCircle : MonoBehaviour
{
    [Header("设置生成的数量")]
    [SerializeField] int iconCount = 30;

    [Header("需要生成的预设")]
    [SerializeField] GameObject prefab;

    [Header("设置中心点,同样也是父物体 ")]
    [SerializeField] Transform originObj;

    [Header("设置圆半径物体")]
    [SerializeField] Transform radiusObj;

    //圆半径 
    float fRadius = 500;


    void Start()
    {
        //计算圆半径
        fRadius = Vector3.Distance(originObj.position, radiusObj.position);
        CreatCircle(); //创建圆环
    }

    #region 围绕一个点生成圆
    int childCount;    //孩子数量
    public void CreatCircle()
    {
        childCount = originObj.childCount;

        float angle = 360f / iconCount; //计算每个物体的角度

        for (int i = 0; i < iconCount; i++)
        {
            GameObject go = GetPrefab(i);

            //sin cos求x,y值
            float x = fRadius * Mathf.Sin((angle * i) * (Mathf.PI / 180f));
            float y = fRadius * Mathf.Cos((angle * i) * (Mathf.PI / 180f));

            go.transform.localPosition = new Vector3(x, y, 0);
            go.transform.localEulerAngles = new Vector3(0, 0, Mathf.Abs(angle * i - 360));

            go.name = i.ToString();
        }
    }


    //获取预设
    GameObject GetPrefab(int index)
    {
        GameObject obj = null;
        if (index < childCount)
            obj = originObj.GetChild(index).gameObject;
        else
            obj = Instantiate(prefab, originObj);
        obj.SetActive(true);

        return obj;
    }
    #endregion

}

?界面布局:

?好的下面让我们来看看效果:

?但是我们的圆只需要展示部分图片,所以我们需要把多余的图片删除并将这个圆环拖拽成预设。留着备用,但是问题来了,如果我们一开始盲猜圆的大小、图片的数量来创建圆环往往是不精确,这样的话做出来的圆并不是我们想要的,所以要制作一个我们想要的圆环,我这里优化了一下,代码中有解释,这里就不多说了。

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

#if UNITY_EDITOR
using UnityEditor;
#endif

#if UNITY_EDITOR
//窗口编辑脚本,用于创建属性面板的创建、保存预设按钮
[CustomEditor(typeof(CreateCircle))]
public class CreateCircleEditor : Editor
{
    public override void OnInspectorGUI()
    {
        DrawDefaultInspector();

        CreateCircle myScript = (CreateCircle)target;

        //创建按钮
        if (GUILayout.Button("Create"))
        {
            myScript.CreatCircle();
        }

        //保存预设按钮
        if (GUILayout.Button("Save"))
        {
            myScript.SavePrefab();
        }
    }
}
#endif



/// <summary>
/// 创建圆环
/// </summary>
public class CreateCircle : MonoBehaviour
{
    [Header("生成的数量")]
    [SerializeField] int iconCount = 30;

    [Header("需要生成的预设")]
    [SerializeField] GameObject prefab;

    [Header("设置中心点,同样也是父物体 ")]
    [SerializeField] Transform originObj;

    [Header("设置圆半径物体")]
    [SerializeField] Transform radiusObj;

    [Header("设置保存预设路径")]
    [SerializeField] string savePath = "Assets/06_Prefabs";

    //圆半径 
    float fRadius;

    void Start()
    {
    }

    #region 围绕一个点生成圆
    bool isSuccessful; //是否成功
    int childCount;    //孩子数量
    public void CreatCircle()
    {
        fRadius = Vector3.Distance(originObj.position, radiusObj.position); //计算圆半径

        DestroyPrefab(); //销毁多余预设
        childCount = originObj.childCount;

        float angle = 360f / iconCount; //计算每个物体的角度

        for (int i = 0; i < iconCount; i++)
        {
            GameObject go = GetPrefab(i);

            //sin cos求x,y值
            float x = fRadius * Mathf.Sin((angle * i) * (Mathf.PI / 180f));
            float y = fRadius * Mathf.Cos((angle * i) * (Mathf.PI / 180f));

            go.transform.localPosition = new Vector3(x, y, 0);
            go.transform.localEulerAngles = new Vector3(0, 0, Mathf.Abs(angle * i - 360));

            go.name = i.ToString();
        }
    }

    //销毁多余预设
    void DestroyPrefab()
    {
        int count = originObj.childCount - iconCount;
        for (int i = 0; i < count; i++) 
        {
            Debug.Log(count); 
            DestroyImmediate(originObj.GetChild(i).gameObject); //使用立即销毁方法,如果使用Destroy会有延迟导致创建不成功
        }
    }

    //获取预设
    GameObject GetPrefab(int index)
    {
        GameObject obj = null;
        if (index < childCount)
            obj = originObj.GetChild(index).gameObject;
        else
            obj = Instantiate(prefab, originObj);
        obj.SetActive(true);

        return obj;
    }
    #endregion

    #region 保存预设
    public void SavePrefab()
    {
        //判断路径是否存在
        if (!File.Exists(savePath))
            Directory.CreateDirectory(savePath);

#if UNITY_EDITOR
        PrefabUtility.SaveAsPrefabAsset(originObj.gameObject, savePath + "/Circle.prefab", out isSuccessful);
#endif
        Debug.Log("是否成功" + isSuccessful);
    }
    #endregion

}

修改后的效果:

?现在我们可以灵活的创建圆环了,我们圆环能看到的其实只有一部分,另一部分的圆环看不到就可以删除了,删除后我们给圆环从左到右排列一下,因为生成的圆是以终点为中心,往左右创建的对称半圆,所以根据如下操作可以快速排列:

?做完这些后按下save保存按钮就可以自动创建这个半圆预设了。

?好的我们的半圆预设创建完成,那么接下来就该实现图片的轮播效果了,我们的轮播效果是当半圆最左边(或最右边)的图片,超出了我们的视野范围内后,就修改位置和旋转到最右边(或最左边,也就是半环的屁股后面),同时判断图片精灵列表中的图片是否都显示过,如果没有就修改图片精灵,这样形成一个循环的过程。

做这个最难点就是如果判断圆环超出了我们的视野范围呢?,其实我们在创建圆环的时候就知道了圆环每旋转多少度就生成一张图片,我上面创建了一个55张图片的圆环,所以圆环每移动6.545度(360度/55张图片约等于6.545度)就代表移动到了下一张图片的位置,这时候根据圆环是向左(或向右)转来修改第一张图片还是最后一张图片的位置。就可以了。这么说有点抽象,我们下面开始做。

1.首先记录一下左右两张图片的位置,这两张图片直接从圆环中复制出一个就可以了,布局如下

?2.脚本

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

/// <summary>
/// 圆环轮播
/// </summary>
public class RoundRobin : MonoBehaviour
{
    //计算方式:360°/图片数量
    float angle;
    [SerializeField] float speed = 10f;
    [SerializeField] Transform start;
    [SerializeField] Transform end;


    [SerializeField] List<Sprite> spriteList; //存放的图片精灵

    void Start()
    {
        angle = 360f / 55f;
        //初始化已有的图片
        for (int i = 0; i < transform.childCount; i++)
            SetImgSprite(1, transform.GetChild(i).GetComponent<Image>());

    }

    float oldRotX;
    void Update()
    {
        float h = Input.GetAxis("Horizontal");
        if (h != 0)
        {
            float rotX = -(h * speed * Time.deltaTime);
            transform.rotation *= Quaternion.Euler(transform.rotation.x, transform.rotation.y, rotX);

            //物体 位置 旋转 孩子下标
            Transform obj;
            Vector3 pos;
            Vector3 rot;
            int childIndex;
            int spriteIndex; //精灵下标 -1或1

            //超出或等于角度
            if (Mathf.Abs(oldRotX - transform.eulerAngles.z) >= angle)
            {
                if (rotX > 0)
                {
                    spriteIndex = 1;
                    //获取物体 位置 旋转 要修改的下标
                    obj = transform.GetChild(0);
                    pos = transform.InverseTransformPoint(end.position);
                    rot = end.eulerAngles - transform.eulerAngles;
                    childIndex = transform.childCount - 1;

                }
                else
                {
                    spriteIndex = -1;

                    //获取物体 位置 旋转 要修改的下标
                    obj = transform.GetChild(transform.childCount - 1);
                    pos = transform.InverseTransformPoint(start.position);
                    rot = start.eulerAngles - transform.eulerAngles;
                    childIndex = 0;
                }

                //设置位置 旋转 子物体在父物体的排列位置
                obj.localPosition = pos;
                obj.localEulerAngles = rot;
                obj.SetSiblingIndex(childIndex);

                SetImgSprite(spriteIndex, obj.GetComponent<Image>()); //图片修改

                oldRotX = transform.eulerAngles.z;
            }
        }
    }

    #region 修改图片精灵
    int spritIndex = 0;//图片精灵
    void SetImgSprite(int index, Image img)
    {
        spritIndex += index;

        //超出精灵列表最大值等于第一个
        if (spritIndex > spriteList.Count - 1)
            spritIndex = 0;

        //小于精灵列表最小值等于最后一个sprite
        if (spritIndex < 0)
            spritIndex = spriteList.Count - 1;

        img.sprite = spriteList[spritIndex];
    }
    #endregion
}

?然后运行就可以了。

https://pan.baidu.com/s/1EdLVK-ZHgRI5RBX9JCqI6Q

提取码:syq1

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-05-05 11:52:21  更:2022-05-05 11:55:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 10:47:38-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码