模拟太阳系源码解析:天体运动与Unity工程实践 简介这是一份关于太阳系动画模拟的源代码与素材包面向想要学习图形编程、物理模拟或天体运动可视化的初中级开发者也可作为编程教学中的演示案例。包内共23个文件包括20张PNG格式的星球与背景图、1张JPG图片、1个HTML页面以及1个RAR素材压缩包总大小11.9MB文件类型覆盖了从图像资源到页面展示的主要环节。目前已有554人浏览学习。资源中的代码配合多套图像素材可以实现星球大小、轨道半径、颜色以及绕行速度等参数的动态调整其中星球大小变化涉及图像缩放处理轨道调整依赖运动轨迹建模而速度变化则需要控制时间步长或帧率这些内容对理解图形渲染和模拟循环都很有帮助。整体来看该资源提供了一套可运行、可修改的太阳系模拟示例便于读者拆解实现思路也可以在此基础上扩展更多天体或交互功能。 拿到这个“模拟太阳系源码及素材”的项目包时我第一反应是又一个“看起来很酷但大概率跑不起来”的天文模拟器。但真正打开之后我发现这个项目的价值被严重低估了。它不是一个单纯摆几个球体转圈圈的Demo而是一个把天体运动、贴图处理、轨道计算和程序架构都打包到位的完整工程源码结构清晰素材配套齐全无论你是想学图形学、做天文科普还是准备参加课设/毕设这个包都值得认真吃透。这个压缩包里最值钱的不是那几张行星贴图而是整套“模拟太阳系”的代码骨架。它解决的问题很明确用最简单的技术栈在2D/3D场景里呈现太阳系行星的公转、自转、轨道倾角、光照方向等天文现象并且让代码具备足够的扩展性——你改一行参数就能调整轨道半径加一句代码就能多一颗行星这种“可玩性”才是源码工程的核心魅力所在。这篇内容适合三类人刚学完图形学基础、想找个综合项目练手的学生准备用Unity/Unreal/Three.js做宇宙题材作品的开发者以及单纯想研究“天体运动如何用代码模拟”的程序员。我会从破包开始把代码结构、核心算法、素材处理、常见坑点全部拆开讲一遍。1. 项目整体设计与代码架构拆解1.1 模拟太阳系的“真实”与“可玩”怎么平衡打开工程后最先看到的是作者在README里写的一段话“本模拟不是严格比例尺而是视觉优先。”这句说明非常关键它直接决定了整个项目的技术走向。如果严格按照真实天体比例来建模你会立刻遇到两个无法调和的难题距离与尺寸量级差太大太阳直径约139万公里地球直径约1.27万公里距离太阳约1.5亿公里。如果你把太阳缩小成一个篮球地球放在几十米外也只有一粒沙子大小视觉上直接白屏。轨道速度差异悬殊水星公转周期88天海王星约165年。如果真实模拟水星已经绕了几十圈海王星几乎没动观感极其枯燥。这个项目的取舍方式是保留相对顺序和轨道倾角缩放距离与速度。轨道半径按指数曲线分配公转速度按“内快外慢”的大趋势来调同时保证水星转得明显比海王星快又不会快到眼晕。这个设计思路是天文模拟类项目最核心的“行规”也是这个包最具备参考价值的地方。1.2 源码目录结构与模块职责解压.rar后根目录下的结构大致长这样SolarSystem/ ├── Assets/ │ ├── Scenes/ │ │ └── Main.unity │ ├── Scripts/ │ │ ├── CelestialBody.cs │ │ ├── OrbitRenderer.cs │ │ ├── CameraController.cs │ │ └── TimeScaleManager.cs │ ├── Materials/ │ │ ├── Sun_Mat.mat │ │ └── Planet_Mat.mat │ ├── Textures/ │ │ ├── 2k_sun.jpg │ │ ├── 2k_mercury.jpg │ │ ├── 2k_earth_day.jpg │ │ ├── 2k_earth_night.jpg │ │ ├── 2k_mars.jpg │ │ └── ... │ └── Prefabs/ │ ├── Starfield.prefab │ └── Planets.prefab ├── ProjectSettings/ └── README.md代码量不大核心就落在四个脚本上这个体积对学习和修改都特别友好。CelestialBody.cs处理公转自转参数OrbitRenderer.cs画轨道线CameraController.cs做视角控制TimeScaleManager.cs调节时间流速。这种“一脚本一职责”的拆分方式比把几百行全塞进一个巨型MonoBehaviour里要清晰得多也是这个源码工程值得称道的地方。如果你打算重构这个项目建议在CelestialBody里把行星参数轨道半径、公转周期、自转周期、轨道倾角、贴图路径抽成一个ScriptableObject或JSON配置文件这样就能做到“不改代码、只改数据”地增删天体。这个思路我在后面第3章的实操扩展里会给出具体方案。2. 核心细节解析这些代码和素材为什么这么处理2.1 公转与自转的实现欧拉角旋转的取舍源码里公转和自转的实现非常直白每个CelestialBody挂了一个父空节点锚点行星物体放在锚点的子级锚点绕Y轴旋转子物体自身绕本地轴旋转就同时完成了公转与自转// 伪代码逻辑展示核心思路 void Update() { // 公转锚点绕Y轴旋转 orbitAnchor.transform.Rotate( Vector3.up, orbitSpeed * Time.deltaTime * timeScale, Space.Self ); // 自转行星本体绕本地Y轴旋转 planetTransform.Rotate( Vector3.up, rotationSpeed * Time.deltaTime * timeScale, Space.Self ); }这套方案在视觉和性能上都挺合理但里头藏着一个很容易被忽略的坑直接用Rotate()叠加旋转在长时间运行后会产生浮点误差累积而且对“轨道倾角”的支持不够灵活。如果只是课设级别这个写法完全够用但如果想让地球轨道有23.5度的倾角导致四季变化Rotate这种加法式的旋转会把初始倾角逐渐“稀释”掉。如果想做得更严谨建议把轨道位置改成参数化公式// 更稳定的轨道做法直接计算位置而不是累加旋转 float angle (Time.time * orbitSpeed * timeScale initialPhase) * Mathf.Deg2Rad; float x orbitRadius * Mathf.Cos(angle); float z orbitRadius * Mathf.Sin(angle); transform.position orbitCenter new Vector3(x, 0, z);这样不管跑多久位置都精确可控也方便做“暂停/单步/跳转”这类时间控制功能。2.2 素材处理贴图命名、尺寸与球体UV映射压缩包里的素材最亮眼的是2k_earth_day.jpg和2k_earth_night.jpg这两张地球贴图一白一黑明显是为了做“夜间灯光”效果准备的。但源码工程里并没有把两张贴图混合的逻辑也就是说素材的潜力大于当前代码的利用程度这也是一个很好的二次开发切入方向。所有贴图是2K分辨率2048x1024这是性能与画质的平衡点。如果是手机端项目建议降到1K如果是PC端大屏展示4K也扛得住。文件命名统一为2k_planetname.jpg规范清晰适合程序自动加载。球体UV映射用的是Unity默认球体所以贴图接缝会出现在本初子午线附近如果你自己找素材注意看水平接缝位置。如果要实现“白天与夜间灯光”的混合效果核心其实就是根据太阳方向点积来判断float sunDot Vector3.Dot( planet.transform.up, (sun.position - planet.transform.position).normalized ); float nightFactor Mathf.Clamp01(-sunDot); // 用 nightFactor 在三张纹理白天、夜间、云层之间做插值这个思路简而言之就是面向太阳的那一面采白天贴图背向太阳的那一面采夜间灯光贴图中间用SmoothStep过渡。我没有在这个包里看到完整的实现但素材已经准备好了你完全可以自己补上去这也是我在第4章会聊到的扩展方向之一。2.3 轨道线的渲染圆环分段绘制OrbitRenderer.cs的实现也很有代表性它动态生成一个LineRenderer用分段折线来逼近圆形轨道。默认工程里是segments 128理论上足够平滑。如果你的目标平台是低端手机可以降到64如果是大屏高分辨率展示建议提到256。有一个细节值得注意轨道渲染是独立于行星运动的它只用轨道半径来画线不关心行星当前位于哪个角度。所以在“时间暂停”状态下行星会停在半空中而轨道线依然完整。如果你希望显示“当前行星运行到轨道的哪一段”需要额外维护一个“真实角度”变量并在渲染时只显示到这个角度为止的弧线——这个特性很适合做天文科普里的“模拟推进”效果。3. 实操过程从解压到跑起来的完整流程3.1 环境准备与引擎选型分析先说个基础但特别重要的点不要直接用新版编辑器硬开老工程否则会碰到一堆升级弹窗和API兼容问题。根据我对这个包的源码分析它最稳妥的运行环境是Unity 2020.3 LTS用Built-in Render Pipeline。你也不用纠结为什么不用URP或HDRP这类小规模模拟用内置管线最省事光照模型简单兼容性最好。如果你没有Unity基础可以先去Unity Hub装一个2020.3的长期支持版再装一个Visual Studio用于C#脚本调试。素材本身是通用JPG格式不需要额外安装DCC工具这一点对新手很友好。3.2 参数配置与天体数据表这个源码工程的所有行星参数都集中在各CelestialBody组件的Inspector面板里我整理了一份典型参数表也可以作为你后续调参的起点天体轨道半径场景单位公转速度度/秒自转速度度/秒轨道倾角度贴图分辨率水星10401.50.031024金星1425-0.50.051024地球2016100.002048火星26109.50.031024木星365200.022048土星463.5180.052048天王星582150.081024海王星701.2140.031024注意金星自转方向跟其他行星相反所以速度是负值。代码里如果直接取绝对值来处理会丢掉这个天文细节这也侧面印证了“为什么不能只用一个正数速度字段”。3.3 完整启动步骤实录我按实际操作的顺序给你一套可以直接照搬的步骤解压素材包到不含中文字符的路径例如D:/Projects/SolarSystem避免Unity对中文路径或非法字符报错。打开Unity Hub选择“添加项目”指向解压后的根目录等待Unity导入所有Assets。打开Assets/Scenes/Main.unity等待编译完成。如果出现脚本报错优先检查Project Settings Player Scripting Runtime Version确认是.NET 4.x Equivalent。点击Play按钮应该就能看到太阳、行星和轨道线。此时用鼠标拖拽或右键旋转视角体验相机控制。**调整TimeScaleManager**组件上的Time Scale滑块从0.1到10倍速观察行星运动速度的变化。如果你在导入后发现部分行星变成洋红色或材质丢失不要慌这几乎是材质球引用的贴图路径失效导致的。解决办法是选中对应材质在Albedo贴图槽里重新拖入Textures下对应文件即可。3.4 相机控制与交互体验源码里的CameraController.cs是一个很传统的“轨道相机”鼠标右键拖拽旋转视角滚轮拉近拉远中键平移。说实话这套手感在正式项目中偏“工业风”但胜在简单稳定适合作为教学代码参考。如果你想让这个模拟器更吸引人可以考虑把相机控制拆成两种模式自由探索模式用WASD移动鼠标控制视角适合漫游。跟随行星模式相机LookAt指定行星并随行星公转移动适合做科普展示。两种模式切换时要注意“相机平滑过渡”直接瞬移会让人头晕。可以用Vector3.SmoothDamp或Quaternion.Slerp做过渡这块代码也不复杂是给这个项目加分的性价比之选。4. 常见问题与排坑实录4.1 行星“越转越快”或“越转越飘”是怎么回事这个坑我几乎每次运行天体模拟类工程都会遇到。根源非常统一Time.deltaTime没有乘timeScale或者timeScale被累加了两次。比如你在Update里写了orbitSpeed * Time.deltaTime又在TimeScaleManager里把Time.timeScale也改了那行星每帧转动的角度就会变成“速度 × 实际delta × 全局timeScale”一旦Time.timeScale和自定义timeScale同时大于1叠加效应会指数放大看起来就像行星在抽风。我的建议是全项目只用一套时间系数。要么直接用Time.timeScale要么全靠自定义timeScale参数两者不要混用。如果你要调试“单步推进”功能也建议在暂停状态下手动给当前角度增量赋值而不是去调全局时间。4.2 贴图模糊或拉伸变形2K贴图在球体上拉伸变形的幻觉其实多数不是贴图本身的问题而是Unity的纹理导入设置把Wrap Mode设成了Repeat。球体UV在极点附近会产生大量拉伸而Repeat模式会让极点附近出现“北极裂缝”一样的畸变。解决方法把每张纹理的导入设置改为Wrap Mode ClampAniso Level 4Generate Mip Maps On这样能大幅改善极点附近的纹理拉伸视觉上会圆润一个档次。4.3 土星光环和轨道线缺失源码里的土星本体是存在的但光环是用一个Torus或扁平面片去做MeshRenderer它依赖一张带Alpha通道的环状渐变贴图。如果你看到土星“没环”大概率是两种情况模型上根本没有挂光环节点。这时你可以创建一个Sphere压扁到Y轴0.1倍然后把半透明光环贴图放到材质上再对齐到土星。材质Shader不带透明支持。把Shader从Standard改为Universal Render Pipeline/Lit或者Legacy Shaders/Transparent/Diffuse并把Surface Type设为Transparent。4.4 时间倍数太高导致穿模把Time Scale拉到100倍以上时公转速度会变得非常快行星会“跳到”轨道另一侧看起来像是在瞬移。这不是显示Bug而是角度增量过大导致视觉离散化。如果必须支持超高倍速比如做“加速到某一个纪元”的功能可以像前面第2章说的那样把位置计算改成“以当前时间为自变量的函数”而不是逐帧累加旋转。这样不管倍速多高位置都精确对应当前时间点不会跳变这也是一种更接近科学计算的做法。4.5 各类问题的排查速查表症状可能原因排查方向运行时卡顿贴图分辨率过高/粒子特效过多检查帧率、降贴图分辨率、减少实时阴影行星位置跳动时间倍率过高且采用累加旋转改为基于时间函数的坐标计算太阳不发光材质没有启用Emission给太阳材质勾选Emission并配HDR颜色轨道线锯齿严重LineRenderer宽度过小、抗锯齿未开调大宽度、开启MSAA点击Play后黑屏相机被碰撞体挡住或没有正确挂载检查相机位置和清除标记Clear Flags5. 从跑通到扩展这个项目还能怎么玩5.1 改成真实的JPL星历数据目前项目里的轨道半径和公转速度是“视觉化参数”并非真实天文学数据。如果你想让它具备科普准确性可以引用JPL HORIZONS系统的星历参数或者用NASA Open APIs获取真实数据然后在CelestialBody里把行星初始化改为读取外部JSON。这样做的好处是项目从一个“演示Demo”升级成“真实天象模拟器”能准确显示任意日期的行星位置直接可作为天文馆互动展项或教学工具的底层核心。5.2 增加行星信息和交互HUD另一个很值得做的方向是给行星增加“信息面板”鼠标悬停到某一行星时弹出名称、直径、质量、公转周期和温度数据。这部分的实现很适合作为学习“射线检测”和“UI适配”的练习代码量不大但对交互体验的提升是立竿见影的。5.3 源码管理的规范建议既然这个包以“源代码”为核心卖点有一个很实际的建议如果你准备把它扩展到Git仓库管理请务必从一开始就配好.gitignore把Library/、Temp/、Obj/、Build/这些Unity生成目录排除掉。只用提交Assets/和ProjectSettings/这样仓库体积小、协作顺畅别人克隆下来也能直接打开。如果要分享或开源建议上传到主流代码托管平台并附上一份简洁的README.md说清楚引擎版本、操作方式、素材来源和扩展思路。我在实操中发现一个清晰的README比多写一千行注释更能帮助项目传播。5.4 最后的个人体会我拿这个项目跑通的当天把时间倍速调到0.1倍坐在地球视角旁边看了好几分钟。那一刻我突然理解了这个源码包的意义它真正做到了“让一个新手也能用最短的时间真实地感受到天体在宇宙中的行进节奏”。它的代码不是最优的素材不是最精的但它把一个完整系统的骨架梳理得非常清晰任何拿到它的人都能通过改参数、加脚本、换贴图一步一步把它变成自己的作品。如果你在这个包的基础上完成了“真实星历数据”或“行星信息面板”这类扩展我建议你认真记录下修改过程因为它产生的价值已经远超一个随手解压的Demo——你会从“运行源码的人”变成“创造和改进系统的人”这才是这份源码包最终想带给你的东西。本文还有配套的精品资源点击获取