Notifications
Article
尝试制作一个球形3D菜单(球形阵列)
Published 9 months ago
168
0
尝试制作一个球形3D菜单,也可用于其他球面分布需求
这次想做一个帅气的3D菜单,第一个想到的就是球面分布,并且最好能动态生成,于是做了一下尝试。
具体思路就是先绕球心做第一圈点排布,再向上和向下一圈圈排布。
这里是效果图

但是做出来感觉还是不如几何球体的分布好看啊...
以下是生成代码
using System.Collections; using System.Collections.Generic; using UnityEngine; public class CreatePointsAround : MonoBehaviour { public float _radius; public int _count; public GameObject _obj; public List<GameObject> _objGroup; private float eachAngle; // Use this for initialization void Start() { eachAngle = 360f / _count; MakePoints(); } public void MakePoints() { //生成第一圈对象 MakePointsByCircle(0, _radius); for (float i = 1;i< _count / 4f; i++) { //获取下一个圆与球心距离以及其半径 float height = _radius * Mathf.Sin(i * eachAngle * Mathf.Deg2Rad); float thisRadius = _radius * Mathf.Cos(i * eachAngle * Mathf.Deg2Rad); //向上生成 MakePointsByCircle(height, thisRadius); //向下生成 MakePointsByCircle(-height, thisRadius); } } /// <summary> /// 生成一圈对象 /// </summary> /// <param name="yPosition"></param> /// <param name="thisRadius"></param> public void MakePointsByCircle(float yPosition, float thisRadius) { Vector2 firstPoint = new Vector2(0, thisRadius); Vector2 nextPoint = firstPoint; for (int i = 0; i < _count; i++) { //生成新对象 GameObject createdPoint = Instantiate(_obj, Vector3.zero, Quaternion.identity, this.transform); //向对象组添加新生成的对象 _objGroup.Add(createdPoint); createdPoint.name = "obj" + i; createdPoint.tag = "objAround"; //这里用一个脚本操控对象慢慢位移到目标点(不知道为啥canvas直接instantiate坐标会有问题) LerpToPosition createdMove = createdPoint.AddComponent<LerpToPosition>(); createdMove.positionTo = new Vector3(nextPoint.x, yPosition, nextPoint.y) + this.transform.position; //获取下一个点 nextPoint = MakeNextHorizontalPoint(nextPoint, thisRadius); } } /// <summary> /// 获取当前圆上下一个点的坐标 /// </summary> /// <param name="thisPoint">当前点坐标</param> /// <param name="eachAngle">每两个相邻点与圆心连线之间的夹角</param> /// <param name="thisRadius">当前圆半径</param> /// <returns></returns> public Vector2 MakeNextHorizontalPoint(Vector2 thisPoint,float thisRadius) { Vector2 nextPoint = new Vector2(); float thisAngle = getThisAngle(thisPoint); //下一个点和初始点与圆心连线的夹角 float nextAngle = thisAngle + eachAngle; //Debug.Log(nextAngle); //获取下一个点的坐标 nextPoint.x = thisRadius * Mathf.Sin(nextAngle * Mathf.Deg2Rad); nextPoint.y = thisRadius * Mathf.Cos(nextAngle * Mathf.Deg2Rad); return nextPoint; } /// <summary> /// 获取点所在半径与初始点所在半径的夹角(0~360°) /// </summary> /// <param name="thisPoint">当前点坐标(忽视y轴)</param> /// <returns>返回0~360°的夹角</returns> float getThisAngle(Vector2 thisPoint) { float thisAngle; //这里如果不用角度想用弧度来算的话,把90改成Mathf.PI,再把对应的Rad2Deg和Deg2Rad改掉就ok了(大概) if (thisPoint.x >= 0 && thisPoint.y > 0) { thisAngle = Mathf.Rad2Deg * Mathf.Atan(thisPoint.x / thisPoint.y); } else if (thisPoint.x > 0 && thisPoint.y <= 0) { thisAngle = -Mathf.Rad2Deg * Mathf.Atan(thisPoint.y / thisPoint.x) + 90; } else if (thisPoint.x <= 0 && thisPoint.y < 0) { thisAngle = Mathf.Rad2Deg * Mathf.Atan(thisPoint.x / thisPoint.y) + 180; } else if (thisPoint.x < 0 && thisPoint.y >= 0) { thisAngle = -Mathf.Rad2Deg * Mathf.Atan(thisPoint.y / thisPoint.x) + 270; } else { thisAngle = 0; } //Debug.Log(thisAngle); return thisAngle; } }
这里是缓慢移动到目标点代码,挂在对象上(这个写的比较随意,应该有其他比较好的方法)
using System.Collections; using System.Collections.Generic; using UnityEngine; public class LerpToPosition : MonoBehaviour { public int _maxLerpCount = 100; [HideInInspector] public Vector3 positionTo; private bool doLerp; private int lerpCount; // Use this for initialization void Start () { scroll thisScrollScript = this.GetComponent<scroll>(); if(thisScrollScript != null) { thisScrollScript.enabled = false; } doLerp = true; } // Update is called once per frame void Update () { if (doLerp) { this.transform.position = Vector3.Lerp(this.transform.position, positionTo, 0.1f); lerpCount++; if(lerpCount >= _maxLerpCount) { doLerp = false; scroll thisScrollScript = this.GetComponent<scroll>(); if (thisScrollScript != null) { thisScrollScript.enabled = true; } } } } }
剩下的就是旋转,我是用射线(Raycast )+ 球体碰撞(SphereCollider),感觉也可以用UI的拖拽(Drag)来做,这里就不写了。
如果有哪位大大知道怎么算几何球体顶点分布,希望能指点一下,谢谢!
如果有什么好的建议也希望能在评论告知,谢谢!

迷彩大兵
软件开发工程师 - Programmer
2
Comments