3D 游戏开发
Unity 最初就是作为 3D 引擎诞生的,其 3D 开发功能非常强大。本章将介绍 3D 游戏开发的核心概念。
3D 基础概念
坐标系
Unity 使用左手坐标系:
- X 轴:水平方向(右为正)
- Y 轴:垂直方向(上为正)
- Z 轴:深度方向(前为正)
Y (上)
│
│ Z (前)
│ ╱
│ ╱
│ ╱
└────────── X (右)
3D 对象基础组件
每个 3D 对象通常包含:
GameObject
├── Transform - 位置、旋转、缩放
├── Mesh Filter - 网格数据
├── Mesh Renderer - 渲染器
└── Collider - 碰撞器(可选)
3D 模型
支持的模型格式
| 格式 | 说明 |
|---|---|
| FBX | 推荐格式,支持动画、材质 |
| OBJ | 简单格式,仅几何体 |
| 3DS | 3ds Max 格式 |
| DAE (COLLADA) | 交换格式 |
| GLTF/GLB | 现代 Web 格式 |
导入设置
选中模型文件,Inspector 中的关键设置:
Model 标签:
- Scale Factor:缩放系数
- Mesh Compression:网格压缩级别
- Read/Write Enabled:允许代码读写网格
- Generate Colliders:自动生成碰撞器
Rig 标签(动画):
- Animation Type:动画类型
None- 无动画Legacy- 旧版动画Generic- 通用动画(非人形)Humanoid- 人形动画(可重定向)
Materials 标签:
- Extract Materials:提取材质到项目
- Texture Import:纹理导入设置
Mesh(网格)
Mesh 是 3D 物体的几何形状,由顶点、边和面组成。
Mesh Filter 和 Mesh Renderer
public class MeshManipulation : MonoBehaviour
{
public MeshFilter meshFilter;
public MeshRenderer meshRenderer;
void Start()
{
// 更换网格
meshFilter.mesh = someOtherMesh;
// 修改材质
meshRenderer.material = newMaterial;
meshRenderer.material.color = Color.red;
// 启用/禁用渲染
meshRenderer.enabled = false;
}
}
程序化生成 Mesh
public class ProceduralMesh : MonoBehaviour
{
void Start()
{
Mesh mesh = new Mesh();
// 定义顶点
Vector3[] vertices = new Vector3[]
{
new Vector3(0, 0, 0),
new Vector3(1, 0, 0),
new Vector3(0, 1, 0),
new Vector3(1, 1, 0)
};
// 定义三角形(顺时针为正面)
int[] triangles = new int[]
{
0, 2, 1, // 第一个三角形
2, 3, 1 // 第二个三角形
};
// 定义 UV
Vector2[] uv = new Vector2[]
{
new Vector2(0, 0),
new Vector2(1, 0),
new Vector2(0, 1),
new Vector2(1, 1)
};
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.uv = uv;
// 重新计算法线
mesh.RecalculateNormals();
GetComponent<MeshFilter>().mesh = mesh;
}
}
材质与纹理
Material(材质)
材质定义了物体表面的外观属性。
常用 Shader
| Shader | 用途 |
|---|---|
| Standard | PBR 物理渲染,最常用 |
| Standard (Specular) | 高光工作流程 |
| Unlit | 不受光照影响,用于 UI、特效 |
| Particles | 粒子效果 |
| Skybox | 天空盒 |
PBR 材质属性
public class MaterialController : MonoBehaviour
{
public Material material;
void Start()
{
// 基础颜色
material.SetColor("_Color", Color.white);
// 金属度 (0-1)
material.SetFloat("_Metallic", 0.5f);
// 光滑度 (0-1)
material.SetFloat("_Glossiness", 0.5f);
// 法线贴图强度
material.SetFloat("_BumpScale", 1f);
}
}
纹理类型
| 纹理 | 说明 |
|---|---|
| Albedo/Diffuse | 基础颜色 |
| Normal Map | 法线贴图,模拟表面凹凸 |
| Metallic | 金属度贴图 |
| Roughness/Smoothness | 粗糙度/光滑度贴图 |
| Occlusion | 环境光遮蔽 |
| Emission | 自发光 |
光照系统
光源类型
// 代码创建光源
public class LightController : MonoBehaviour
{
void CreateLight()
{
GameObject lightGO = new GameObject("MyLight");
Light light = lightGO.AddComponent<Light>();
light.type = LightType.Point; // 点光源
light.color = Color.yellow;
light.intensity = 1.5f;
light.range = 10f;
}
}
| 光源类型 | 特点 |
|---|---|
| Directional | 平行光,模拟太阳光,无位置只有方向 |
| Point | 点光源,向四面八方发光,如灯泡 |
| Spot | 聚光灯,圆锥形光照,如手电筒 |
| Area | 区域光,矩形发光面,仅烘焙可用 |
光照模式
- Realtime:实时光照,动态计算
- Mixed:混合模式,部分烘焙部分实时
- Baked:完全烘焙,性能最好但不动态
全局光照(GI)
Window > Rendering > Lighting
- Baked GI:预计算静态物体的光照
- Realtime GI:实时全局光照
- Reflection Probes:反射探头,捕捉环境反射
3D 物理
Rigidbody 3D
public class Physics3DController : MonoBehaviour
{
public Rigidbody rb;
void Start()
{
// 设置质量
rb.mass = 2f;
// 设置阻力
rb.drag = 0.5f;
// 使用重力
rb.useGravity = true;
// 是否受物理影响
rb.isKinematic = false;
}
void Update()
{
// 施加力
rb.AddForce(Vector3.forward * 10f);
// 施加扭矩(旋转)
rb.AddTorque(Vector3.up * 5f);
// 直接设置速度
rb.velocity = new Vector3(0, 5, 0);
// 爆炸效果
rb.AddExplosionForce(1000f, explosionPos, 10f);
}
}
3D 碰撞器
| 碰撞器 | 用途 |
|---|---|
| Box Collider | 立方体碰撞 |
| Sphere Collider | 球体碰撞 |
| Capsule Collider | 胶囊体碰撞 |
| Mesh Collider | 网格碰撞(精确但性能低) |
| Terrain Collider | 地形碰撞 |
| Wheel Collider | 车轮碰撞(载具专用) |
物理材质
创建 Physic Material 控制摩擦和弹性:
| 属性 | 说明 |
|---|---|
| Dynamic Friction | 动态摩擦系数 |
| Static Friction | 静态摩擦系数 |
| Bounciness | 弹性(0-1) |
| Friction Combine | 摩擦组合方式 |
| Bounce Combine | 弹性组合方式 |
地形系统(Terrain)
创建地形
- GameObject > 3D Object > Terrain
- 在 Inspector 中使用地形工具
地形工具
| 工具 | 功能 |
|---|---|
| Raise/Lower | 升高/降低地形 |
| Paint Height | 绘制特定高度 |
| Smooth Height | 平滑地形 |
| Paint Texture | 绘制纹理图层 |
| Paint Trees | 种植树木 |
| Paint Details | 绘制草和细节 |
| Settings | 地形设置 |
地形组件代码
public class TerrainModifier : MonoBehaviour
{
public Terrain terrain;
void ModifyTerrain()
{
TerrainData terrainData = terrain.terrainData;
// 获取高度图
float[,] heights = terrainData.GetHeights(0, 0,
terrainData.heightmapResolution,
terrainData.heightmapResolution);
// 修改高度
heights[50, 50] = 0.5f; // 0-1 范围
// 应用修改
terrainData.SetHeights(0, 0, heights);
}
}
相机系统
Camera 组件
public class CameraController3D : MonoBehaviour
{
public Camera cam;
public Transform target;
void Start()
{
// 设置背景色
cam.backgroundColor = Color.black;
// 设置视场角
cam.fieldOfView = 60f;
// 设置裁剪面
cam.nearClipPlane = 0.3f;
cam.farClipPlane = 1000f;
// 正交模式(2.5D 游戏常用)
cam.orthographic = false;
cam.orthographicSize = 5f;
}
// 第三人称跟随
void LateUpdate()
{
Vector3 offset = new Vector3(0, 5, -10);
transform.position = target.position + offset;
transform.LookAt(target);
}
}
多相机设置
public class MultiCameraSetup : MonoBehaviour
{
public Camera mainCamera;
public Camera minimapCamera;
void SetupCameras()
{
// 主相机
mainCamera.depth = 0;
mainCamera.rect = new Rect(0, 0, 1, 1);
// 小地图相机
minimapCamera.depth = 1;
minimapCamera.rect = new Rect(0.7f, 0.7f, 0.25f, 0.25f);
minimapCamera.clearFlags = CameraClearFlags.Depth;
}
}
天空盒与雾效
天空盒设置
public class EnvironmentSetup : MonoBehaviour
{
public Material skyboxMaterial;
void Start()
{
// 设置天空盒
RenderSettings.skybox = skyboxMaterial;
// 设置环境光
RenderSettings.ambientMode = UnityEngine.Rendering.AmbientMode.Skybox;
RenderSettings.ambientIntensity = 1f;
// 设置雾
RenderSettings.fog = true;
RenderSettings.fogMode = FogMode.Exponential;
RenderSettings.fogColor = Color.gray;
RenderSettings.fogDensity = 0.01f;
}
}
实践:简单的 3D 第三人称控制器
public class ThirdPersonController : MonoBehaviour
{
[Header("移动")]
public float moveSpeed = 5f;
public float rotationSpeed = 10f;
[Header("跳跃")]
public float jumpForce = 8f;
public LayerMask groundLayer;
[Header("组件")]
public Rigidbody rb;
public Transform cameraTransform;
public Transform groundCheck;
private bool isGrounded;
private Vector3 moveDirection;
void Update()
{
// 地面检测
isGrounded = Physics.CheckSphere(groundCheck.position, 0.3f, groundLayer);
// 获取输入
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
// 计算移动方向(相对于相机)
Vector3 forward = cameraTransform.forward;
Vector3 right = cameraTransform.right;
forward.y = 0;
right.y = 0;
forward.Normalize();
right.Normalize();
moveDirection = forward * vertical + right * horizontal;
// 跳跃
if (Input.GetButtonDown("Jump") && isGrounded)
{
rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
}
// 旋转角色
if (moveDirection != Vector3.zero)
{
Quaternion targetRotation = Quaternion.LookRotation(moveDirection);
transform.rotation = Quaternion.Slerp(transform.rotation,
targetRotation, rotationSpeed * Time.deltaTime);
}
}
void FixedUpdate()
{
// 应用移动
rb.MovePosition(rb.position + moveDirection * moveSpeed * Time.fixedDeltaTime);
}
}
下一步
掌握 3D 开发基础后,你可以:
- 学习 动画系统 制作角色动画
- 了解 渲染管线 优化画面效果
- 探索 Shader 基础 创建自定义材质
- 学习 光照与阴影 提升场景氛围