准备一张贴图
![](https://i-blog.csdnimg.cn/blog_migrate/603b5bed6ddc54e0380ca41c63673d6b.png)
创建材质球
![](https://i-blog.csdnimg.cn/blog_migrate/d8360e40423a454963ca86fdb4f36cff.png)
球面坐标系转直角坐标系
x=rsinθcosφ.
y=rsinθsinφ.
z=rcosθ.
![](https://i-blog.csdnimg.cn/blog_migrate/2fb8ced0a04d25dc30257d817a36b543.png)
效果如下
![](https://i-blog.csdnimg.cn/blog_migrate/4a73afe80be522f6caa19a2ff5750f4d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/27dff4f3fd66967ca7d6054aecd13e19.png)
![](https://i-blog.csdnimg.cn/blog_migrate/105577bcefb5e7f4dfde8f674c5d5a97.png)
脚本如下
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//创建球形mesh
public class BallCreater : MonoBehaviour {
public Material ballMat;//材质
void Start () {
createBall("mEarth",new Vector3(0,0,0),100.0f,181,88);
}
void Update () {
}
/// <summary>
/// 创建球形mesh
/// </summary>
/// <param name="meshName">名称</param>
/// <param name="center">球心</param>
/// <param name="radius">半径</param>
/// <param name="longPart">经线数</param>
/// <param name="latPart">纬线数</param>
/// <returns></returns>
private GameObject createBall(string meshName,Vector3 center, float radius, int longPart, int latPart)
{
GameObject meshObject = new GameObject(meshName);
int verticeNum = longPart * latPart+2* longPart;//经线数*纬线数+极点处多个重合点 (首尾经线重合)
Vector3[] vertices = new Vector3[verticeNum];//顶点数组
Vector3[] normals = new Vector3[verticeNum];//顶点法线数组
Vector2[] uvs = new Vector2[verticeNum];//uv数组
int[] triangles = new int[(longPart-1)* latPart * 3 * 2];//三角集合数组,保存顶点索引
float degreesToRadians = Mathf.PI / 180.0f; //弧度转换
float deltaLong = 360.0f /(longPart-1);//经度每份对应度数
float deltaLat = 180.0f/ (latPart+2);//纬度每份对应度数
//极点放置多个顶点,同位置不同uv
for (int i = 0; i < longPart; i++)
{
vertices[i] = new Vector3(0, 0, 1) * radius;
normals[i] = vertices[0].normalized;
uvs[i] = new Vector2((float)i/(float)longPart,0);
}
int k = 0;
for (int i = 0; i < longPart-1; i++)
{
triangles[k++] = i;
triangles[k++] = i+ longPart;
triangles[k++] = i + longPart+1;
}
for (int tempLat = 0; tempLat < latPart; tempLat++)
{
float tempAngle1 = ((tempLat+1)* deltaLat) * degreesToRadians;
for (int tempLong = 0; tempLong < longPart; tempLong++)
{
float tempAngle2 = (tempLong*deltaLong) * degreesToRadians;
int tempIndex = tempLong+ tempLat* longPart+ longPart;
vertices[tempIndex] = new Vector3(Mathf.Sin(tempAngle1) * Mathf.Cos(tempAngle2), Mathf.Sin(tempAngle1) * Mathf.Sin(tempAngle2), Mathf.Cos(tempAngle1)) * radius;
normals[tempIndex] = vertices[tempIndex].normalized;
uvs[tempIndex] = new Vector2((float)tempLong / (float)longPart, (float)tempLat / (float)latPart);
if (tempLat!= latPart-1)
{
if (tempLong != longPart-1)
{
triangles[k++] = tempLong + tempLat * longPart + longPart;
triangles[k++] = tempLong + tempLat * longPart + 2 * longPart;
triangles[k++] = tempLong + tempLat * longPart + longPart + 1;
triangles[k++] = tempLong + tempLat * longPart + 2 * longPart;
triangles[k++] = tempLong + tempLat * longPart + 1 + 2 * longPart;
triangles[k++] = tempLong + tempLat * longPart + 1 + longPart;
}
}
}
}
//极点放置多个顶点,同位置不同uv
for (int i = 0; i < longPart; i++)
{
vertices[verticeNum - 1-i] = new Vector3(0, 0, -1) * radius;
normals[verticeNum - 1-i] = vertices[verticeNum - 1].normalized;
uvs[verticeNum - 1-i] = new Vector2(1.0f-(float)i / (float)longPart, 1.0f);
}
for (int i = 0; i < longPart-1; i++)
{
triangles[k++] = verticeNum - 1-i;
triangles[k++] = verticeNum - 1-i- longPart;
triangles[k++] = verticeNum - 2 - i- longPart;
}
Mesh mesh = new Mesh();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.normals = normals;
mesh.uv = uvs;
mesh.RecalculateBounds();
mesh.RecalculateNormals();
meshObject.AddComponent<MeshFilter>();
meshObject.AddComponent<MeshRenderer>();
meshObject.GetComponent<MeshFilter>().mesh = mesh;
meshObject.GetComponent<MeshRenderer>().material = ballMat;
meshObject.transform.position += center;
return meshObject;
}
}