开发环境:Unity 2022.3.5f1c1 + Visual Studio 2022
太阳系相关星体:太阳、八大行星、月球
模拟星系:太阳系、地月系
功能:支持行星以太阳为中心,任意轴进行公转,此处演示同一平面。a1-a8为公转轴,可以任意修改,InitStarPosition()将会修正星体初始位置;MoveAroundSun脚本挂在SolarSystemGroup对象上(空对象)。
动态演示效果
静态展示图片
文章来源:https://uudwc.com/A/12bOo
核心代码文章来源地址https://uudwc.com/A/12bOo
using UnityEngine;
public class MoveAroundSun : MonoBehaviour
{
// 星体
public Transform Sun;
public Transform Mercury;
public Transform Venus;
public Transform Earth;
public Transform Moon;
public Transform Mars;
public Transform Jupiter;
public Transform Saturn;
public Transform Uranus;
public Transform Neptune;
// 公转轴:Mercury至Neptune八大行星
Vector3 a1 = new Vector3(0, 1, 0);
Vector3 a2 = new Vector3(0, 1, 0);
Vector3 a3 = new Vector3(0, 1, 0);
Vector3 a4 = new Vector3(0, 1, 0);
Vector3 a5 = new Vector3(0, 1, 0);
Vector3 a6 = new Vector3(0, 1, 0);
Vector3 a7 = new Vector3(0, 1, 0);
Vector3 a8 = new Vector3(0, 1, 0);
/// <summary>
/// 初始化行星位置,使Star位于以Center为中心,rotateAxis为公转轴的法平面上
/// </summary>
/// <param name="center">公转中心</param>
/// <param name="star">公转行星</param>
/// <param name="rotateAxis">公转轴</param>
void InitStarPosition(Vector3 center, Transform star, Vector3 rotateAxis)
{
// 中心点指向行星的方向向量
Vector3 centerToStar = star.position - center;
// 通过方向向量和公转轴向量的叉乘,得到这两个向量所在平面的法向量
Vector3 normal = Vector3.Cross(rotateAxis, centerToStar);
// 计算方向向量和公转轴向量的角度
float angle = Vector3.Angle(rotateAxis, centerToStar);
// 计算方向向量转动到法向量的角度(转动到法平面上的角度)
float rotateAngle = Mathf.Abs(90 - angle);
// 以太阳为中心,法向量为转轴来转动角度
star.RotateAround(center, normal, rotateAngle);
}
// Start is called before the first frame update
void Start()
{
// 为了让任意位置的星体都可以绕任意轴旋转,需要在初始时刻定位星体位置(只挂载一个脚本,所以有重复代码)
InitStarPosition(Sun.position, Mercury, a1);
InitStarPosition(Sun.position, Venus, a2);
InitStarPosition(Sun.position, Earth, a3);
InitStarPosition(Sun.position, Mars, a4);
InitStarPosition(Sun.position, Jupiter, a5);
InitStarPosition(Sun.position, Saturn, a6);
InitStarPosition(Sun.position, Uranus, a7);
InitStarPosition(Sun.position, Neptune, a8);
InitStarPosition(Earth.position, Moon, Earth.transform.up);
}
// Update is called once per frame
void Update()
{
Mercury.RotateAround(Sun.position, a1, 20 * Time.deltaTime);
Mercury.Rotate(Vector3.up * 50 * Time.deltaTime);
Venus.RotateAround(Sun.position, a2, 10 * Time.deltaTime);
Venus.Rotate(Vector3.up * 30 * Time.deltaTime);
Earth.RotateAround(Sun.position, a3, 10 * Time.deltaTime);
Earth.Rotate(Vector3.up * 30 * Time.deltaTime);
Moon.transform.RotateAround(Earth.position, Vector3.up, 359 * Time.deltaTime);
Mars.RotateAround(Sun.position, a4, 8 * Time.deltaTime);
Mars.Rotate(Vector3.up * 30 * Time.deltaTime);
Jupiter.RotateAround(Sun.position, a5, 7 * Time.deltaTime);
Jupiter.Rotate(Vector3.up * 30 * Time.deltaTime);
Saturn.RotateAround(Sun.position, a6, 6 * Time.deltaTime);
Saturn.Rotate(Vector3.up * 30 * Time.deltaTime);
Uranus.RotateAround(Sun.position, a7, 5 * Time.deltaTime);
Uranus.Rotate(Vector3.up * 30 * Time.deltaTime);
Neptune.RotateAround(Sun.position, a8, 4 * Time.deltaTime);
Neptune.Rotate(Vector3.up * 30 * Time.deltaTime);
}
}