Unity音量滑块沿弧形移动

news/2024/10/30 1:25:40/

一、音量滑块的移动

1、滑块在滑动的时候,其运动轨迹沿着大圆的弧边展开
2、滑块不能无限滑动,而是两端各有一个挡块,移动到挡块位置,则不能往下移动,但可以折回
3、鼠标悬停滑块时,给出音量值和操作提示
4、移动滑块的时候,始终提示音量的值,停止移动后,音量值消失
请添加图片描述

二、UI实现

如下图所示:
1、滑块的移动是围绕大圆的圆心旋转实现的,所以滑动的时候,是大圆在旋转,滑块是大圆的子物体
2、滑块移动是通过鼠标左右移动来实现的
3、音量值是通过夹角计算来获取的
在这里插入图片描述

三、思路

1、当前滑块位置代表多大的音量值 e.g.[50%]

滑块A可移动的角度范围计算:角度BOC
滑块A当前位置的角度计算:角度BOA
volume = 角度BOA / 角度BOC

如何计算角度?

/// <summary>/// 计算两条射线之间的夹角(AB,AC -> ∠BAC)/// </summary>/// <param name="A">原点</param>/// <param name="B">位置1</param>/// <param name="C">位置2</param>/// <returns>夹角(以度为单位)</returns>public static float GetClamAngle(Vector3 A, Vector3 B, Vector3 C){// 计算向量 ABVector3 AB = B - A;// 计算向量 ACVector3 AC = C - A;// 计算 AB 和 AC 之间的夹角(以度为单位)float angle = Vector3.Angle(AB, AC);// 返回夹角return angle;}

计算可以滑动的角度范围值

//计算滑块运行区间的总的角度范围
allAngle = GetClamAngle(O.transform.position, B.transform.position,C.transform.position);

在这里插入图片描述

2、鼠标左右拖拽滑块的时候,滑块沿着大圆进行旋转

鼠标x分量的获取

PointerEventData .delta.x

拖拽旋转的实现

//拖拽中:
ObjectHandle.GetComponent<EventTrigger>().AddListener(EventTriggerType.Drag, (PointerEventData eventData) =>
{float direction = Mathf.Sign(eventData.delta.x);Quaternion rotation = Quaternion.AngleAxis(direction * rotateSpeed, Vector3.forward);ObjectToRotate.transform.rotation *= rotation;
});

限位的实现
左上限位:滑块A.x <= C.x的时候,不能再往左转
右下限位:滑块A.y <= B.y的时候,不能再往下转
在这里插入图片描述

//极限位控制
if (ObjectHandle.transform.position.x <= leftBlock.transform.position.x)
{ObjectHandle.transform.position = leftBlock.transform.position;
}
if (ObjectHandle.transform.position.y <= rightBlock.transform.position.y)
{ObjectHandle.transform.position = rightBlock.transform.position;
}

四、代码

using System;
using System.Collections;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using static txlib;/// <summary>
/// 音量控制:拖动bar进行进行滑动,左上位置为最高音量,右下位置为最低音量
/// </summary>
public class DragVolumBar : MonoBehaviour
{/// <summary>/// 要旋转的物体/// </summary>[Header("要旋转的物体")][SerializeField]public GameObject ObjectToRotate;/// <summary>/// 控制旋转的bar/// </summary>[Header("控制旋转的bar")][SerializeField]public GameObject ObjectHandle;/// <summary>/// 左侧挡板/// </summary>[Header("左侧挡板")][SerializeField]public GameObject leftBlock;/// <summary>/// 右侧挡板/// </summary>[Header("右侧挡板")][SerializeField]public GameObject rightBlock;/// <summary>/// 旋转的速度包含方向/// </summary>[Header("旋转的速度包含方向")][SerializeField] public float rotateSpeed = 10f;/// <summary>/// 用于显示音量值的text/// </summary>[Header("用于显示音量值的text")][SerializeField]public TMP_Text textVolume;/// <summary>/// 音量大小/// </summary>public static float volume;/// <summary>/// 滑块滑动时的角度区间范围/// </summary>private float allAngle;/// <summary>/// 计算两条射线之间的夹角(AB,AC -> ∠BAC)/// </summary>/// <param name="A">原点</param>/// <param name="B">位置1</param>/// <param name="C">位置2</param>/// <returns>夹角(以度为单位)</returns>public static float GetClamAngle(Vector3 A, Vector3 B, Vector3 C){// 计算向量 ABVector3 AB = B - A;// 计算向量 ACVector3 AC = C - A;// 计算 AB 和 AC 之间的夹角(以度为单位)float angle = Vector3.Angle(AB, AC);// 返回夹角return angle;}// Start is called before the first frame updatevoid Start(){textVolume.gameObject.SetActive(false);//计算滑块运行区间的总的角度范围allAngle = GetClamAngle(ObjectToRotate.transform.position, leftBlock.transform.position,rightBlock.transform.position);if (!ObjectHandle.GetComponent<EventTrigger>()) ObjectHandle.AddComponent<EventTrigger>();#region 音量滑块拖动//开始拖拽:ObjectHandle.GetComponent<EventTrigger>().AddListener(EventTriggerType.BeginDrag, async (PointerEventData eventData) =>{textVolume.gameObject.SetActive(true);});//拖拽中:ObjectHandle.GetComponent<EventTrigger>().AddListener(EventTriggerType.Drag, (PointerEventData eventData) =>{float direction = Mathf.Sign(eventData.delta.x);Quaternion rotation = Quaternion.AngleAxis(direction * rotateSpeed, Vector3.forward);ObjectToRotate.transform.rotation *= rotation;//极限位控制if (ObjectHandle.transform.position.x <= leftBlock.transform.position.x){ObjectHandle.transform.position = leftBlock.transform.position;}if (ObjectHandle.transform.position.y <= rightBlock.transform.position.y){ObjectHandle.transform.position = rightBlock.transform.position;}var angle = GetClamAngle(ObjectToRotate.transform.position, ObjectHandle.transform.position,rightBlock.transform.position);volume = angle / allAngle;Debug.Log($"总角度:{allAngle},当前角度:{angle} ,声音值:{(int)(100 * volume)}");textVolume.text = $"{(int)(100 * volume)}%";});//结束拖拽:延缓隐藏音量值ObjectHandle.GetComponent<EventTrigger>().AddListener(EventTriggerType.EndDrag, async (PointerEventData eventData) =>{await UniTask.Delay(TimeSpan.FromSeconds(0.2f),cancellationToken:this.GetCancellationTokenOnDestroy());textVolume.gameObject.SetActive(false);});#endregion#region 音量滑块鼠标悬停时,显示音量ObjectHandle.GetComponent<EventTrigger>().AddListener(EventTriggerType.PointerEnter, async (PointerEventData eventData) =>{textVolume.gameObject.SetActive(true);var angle = GetClamAngle(ObjectToRotate.transform.position, ObjectHandle.transform.position, rightBlock.transform.position);volume = angle / allAngle;textVolume.text = $"{(int)(100 * volume)}% <color=blue>鼠标左右拖拽滑块来调节音量</color>";});#endregion}
}

http://www.ppmy.cn/news/50804.html

相关文章

FWT学习笔记(快速沃尔什变换)

前言 首先&#xff0c;我们来看看多项式乘法。 f ( x ) a 0 a 1 x a 2 x 2 ⋯ a n x n f(x)a_0a_1xa_2x^2\dotsa_nx^n f(x)a0​a1​xa2​x2⋯an​xn g ( x ) b 0 b 1 x b 2 x 2 ⋯ b n x n g(x)b_0b_1xb_2x^2\dotsb_nx^n g(x)b0​b1​xb2​x2⋯bn​xn 而 h ( x ) …

MySql中,join 语句怎么优化?

既然每次从驱动表取数据比较耗时&#xff0c;那我们每次从驱动表取一批数据放到内存中&#xff0c;然后对这一批数据进行匹配操作。这批数据匹配完毕&#xff0c;再从驱动表中取一批数据放到内存中&#xff0c;直到驱动表的数据全都匹配完毕 批量取数据能减少很多IO操作&#…

基于matlab仿真相控天线阵列在波束成形MIMO-OFDM系统中的使用

一、前言 本例显示了相控阵在采用波束成形的MIMO-OFDM通信系统中的使用。它使用通信工具箱和相控阵系统工具箱中的组件&#xff0c;对组成发射器和前端接收器组件的辐射元件进行建模&#xff0c;用于MIMO-OFDM通信系统。使用用户指定的参数&#xff0c;您可以根据不同空间位置和…

树形DP分析

树形dp 简单来说树形 d p 就是在树上做 d p 罢了 简单来说树形dp就是在树上做dp罢了 简单来说树形dp就是在树上做dp罢了 树嘛&#xff0c;就要符合除了根节点外每个节点只有一个父节点 树嘛&#xff0c;就要符合除了根节点外每个节点只有一个父节点 树嘛&#xff0c;就要符合除…

微信小程序PHP+python+nodejs+springboot+vue 电影院订票选座系统

管理员的主要功能有&#xff1a; 1.管理员输入账户登陆后台 2.个人中心&#xff1a;管理员修改密码和账户信息 3.会员管理&#xff1a;对注册的会员信息进行删除&#xff0c;查询&#xff0c;添加&#xff0c;修改 4.电影分类管理&#xff1a;对电影的分类信息进行添加&#xf…

Canokey Pigeon的初级玩法

Canokey Pigeon的初级玩法 前言开箱使用控制台新版旧版 初步设置FIDO2 PIN更改重置 坑&#xff08;或者说不满意的地方&#xff09;玩法FIDO2/U2FOpenPGPPIVNDEFOATH 参考 本文转载于我的博客Canokey Pigeon的初级玩法 Canokey Pigeon今天终于到货了 {% note warning flat %} …

pt12pymsql使用

pymysql模块 pymysql是一个第三方库&#xff0c;如果自己的计算机上没有可以在终端使用命令进行安装。 pymysql默认开始事务&#xff0c;支持事务的引擎需要commit sudo pip3 install pymysql pymysql使用流程 1. 建立数据库连接&#xff1a;db pymysql.connect(...)…

[oeasy]python0140_导入_import_from_as_namespace_

导入import 回忆上次内容 上次学习了 tryexcept 注意要点 半角冒号缩进输出错误信息 有错就报告 不要隐瞒否则找不到出错位置还可以用traceback把 系统报错信息原样输出 但是代码量好多啊 10多 行了 &#x1f92f;可以把他输入部分和输出部分么&#xff1f;&#x1f914; 我…