在Unity中制作一个完整的3D场景需要包含多个关键模块,包括场景模型的搭建、动画的实现、Navigation导航系统的配置、碰撞检测的设置等。以下将详细讲解每个模块的技术实现步骤,结合实际案例帮助开发者快速掌握3D场景制作的流程。
1. 3D场景的基本搭建
3D场景的制作通常是从模型导入、材质贴图设置、灯光配置开始的。
1.1 导入3D模型
- 导入模型:
- 将
.fbx
、.obj
等3D模型文件复制到Unity的Assets
目录下。 - Unity会自动将模型导入为Prefab,可以直接拖放到场景中使用。
- 将
- 检查模型设置:
- 在Inspector中设置模型的
Scale
(缩放)、Normals
(法线)、Animation
(如有动画)。
- 在Inspector中设置模型的
- 优化模型:
- 删除不必要的多边形,压缩模型大小。
- 使用LOD(Level of Detail)优化远处模型。
示例:设置模型缩放
csharp
复制
GameObject model = Instantiate(Resources.Load<GameObject>("MyModel"));
model.transform.localScale = new Vector3(1f, 1f, 1f); // 调整缩放比例
1.2 材质与贴图
材质与贴图负责为模型提供视觉效果。Unity支持PBR(基于物理的渲染),可以使用标准材质(Standard Shader)或自定义材质。
- 设置材质:
- 在模型的
Renderer
组件中设置材质(Material)。
- 在模型的
- 应用贴图:
- Unity支持多种类型的贴图:
- Albedo:基础颜色贴图。
- Normal Map:法线贴图,用于增加细节。
- Metallic Map:金属度贴图。
- Emission Map:自发光贴图。
- Unity支持多种类型的贴图:
示例:动态更换材质
Renderer renderer = model.GetComponent<Renderer>();
Material newMaterial = Resources.Load<Material>("MyMaterial");
renderer.material = newMaterial;
1.3 灯光与阴影
灯光和阴影在场景搭建中至关重要,可以通过以下步骤实现:
- 添加灯光:
- 在场景中添加
Directional Light
(平行光)、Point Light
(点光源)或Spot Light
(聚光灯)。
- 在场景中添加
- 配置全局光照:
- 在
Lighting
窗口中设置环境光(Ambient Light)和全局光照(Global Illumination)。
- 在
- 烘焙光照:
- 对静态物体进行光照烘焙,减少实时光照的性能消耗。
示例:动态调整灯光强度
Light light = FindObjectOfType<Light>();
light.intensity = 1.5f; // 设置灯光亮度
2. 动画制作与实现
3D场景中的动画通常包括物体动画、角色动画和摄像机动画。
2.1 物体动画
物体动画可以通过Unity的Animation窗口或脚本实现。
1. 使用Animation窗口
- 选中需要添加动画的对象,打开
Window > Animation > Animation
。 - 在时间轴中添加关键帧调整位置、旋转、缩放等属性。
- 保存动画,Unity会自动生成
Animation Clip
。
2. 使用代码实现动画
通过脚本控制物体的旋转、移动等。
示例:物体旋转动画
using UnityEngine;
public class RotateObject : MonoBehaviour
{
public float rotationSpeed = 50f;
void Update()
{
transform.Rotate(Vector3.up, rotationSpeed * Time.deltaTime);
}
}
2.2 骨骼动画
骨骼动画通常用于角色。Unity支持基于Humanoid或Generic的骨骼绑定和动画播放。
1. 导入角色和动画
- 将带有骨骼的模型导入Unity(如
.fbx
文件)。 - 在模型的
Rig
设置中选择Humanoid
或Generic
,然后Apply。 - 配置
Animator Controller
,将动画片段拖入状态机。
2. 动态播放角色动画
示例:通过脚本播放动画
using UnityEngine;
public class CharacterAnimation : MonoBehaviour
{
private Animator animator;
void Start()
{
animator = GetComponent<Animator>();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
animator.SetTrigger("Jump"); // 播放跳跃动画
}
}
}
2.3 摄像机动画
摄像机动画可以通过Timeline或脚本实现。
1. 使用Timeline
- 创建Timeline(右键
Assets > Create > Timeline
)。 - 添加摄像机的
Animation Track
,设置移动路径。 - 在脚本中触发Timeline播放。
2. 使用脚本控制摄像机动画
示例:摄像机平滑移动
using UnityEngine;
public class CameraFollow : MonoBehaviour
{
public Transform target;
public float smoothSpeed = 0.125f;
public Vector3 offset;
void LateUpdate()
{
Vector3 desiredPosition = target.position + offset;
transform.position = Vector3.Lerp(transform.position, desiredPosition, smoothSpeed);
}
}
3. Navigation导航系统
Unity的Navigation系统用于实现NPC的路径规划和自动导航。
3.1 配置导航网格
- 标记导航区域:
- 选中场景中的静态物体,在Inspector中勾选
Navigation Static
。
- 选中场景中的静态物体,在Inspector中勾选
- 烘焙导航网格:
- 打开
Window > AI > Navigation
。 - 在
Bake
选项卡中调整参数(如Agent Radius、Step Height等)。 - 点击
Bake
生成导航网格。
- 打开
3.2 配置NavMesh Agent
- 为NPC添加
NavMeshAgent
组件。 - 在脚本中设置目标点,驱动NPC移动。
示例:NPC自动导航
using UnityEngine;
using UnityEngine.AI;
public class NPCNavigation : MonoBehaviour
{
private NavMeshAgent agent;
public Transform target;
void Start()
{
agent = GetComponent<NavMeshAgent>();
agent.SetDestination(target.position); // 设置目标点
}
}
3.3 动态导航更新
如果场景中有动态物体(如门、平台),需要通过NavMesh Obstacle
动态更新导航网格。
示例:控制障碍物的启用
using UnityEngine;
public class DynamicObstacle : MonoBehaviour
{
public NavMeshObstacle obstacle;
void Update()
{
if (Input.GetKeyDown(KeyCode.O))
{
obstacle.enabled = !obstacle.enabled; // 切换障碍物状态
}
}
}
4. 碰撞检测与物理场景
碰撞检测是3D开发中的重要环节,用于处理物体之间的交互。
4.1 配置碰撞器
- 为物体添加
Collider
(如Box、Sphere、Mesh Collider)。 - 如果物体需要受物理影响,添加
Rigidbody
组件。
4.2 碰撞事件处理
通过OnCollisionEnter
、OnTriggerEnter
等方法处理碰撞事件。
示例:检测碰撞事件
using UnityEngine;
public class CollisionHandler : MonoBehaviour
{
void OnCollisionEnter(Collision collision)
{
Debug.Log("Collided with: " + collision.gameObject.name);
}
void OnTriggerEnter(Collider other)
{
Debug.Log("Entered trigger: " + other.gameObject.name);
}
}
4.3 动态物理交互
通过Rigidbody
控制物体的物理行为。
示例:添加力使物体移动
using UnityEngine;
public class ApplyForce : MonoBehaviour
{
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
rb.AddForce(Vector3.up * 10f, ForceMode.Impulse); // 向上施加力
}
}
}
5. 综合场景制作案例
结合以上模块,可以制作一个带有导航、动画、碰撞的完整场景。
案例:NPC在3D场景中巡逻并与玩家交互
- 场景搭建:
- 导入地形、建筑模型,设置材质和灯光。
- 烘焙导航网格。
- NPC导航:
- 为NPC添加
NavMeshAgent
,设置巡逻路径。
- 为NPC添加
- 玩家交互:
- 玩家碰到NPC时触发动画或对话。
脚本整合示例
using UnityEngine;
using UnityEngine.AI;
public class NPCInteraction : MonoBehaviour
{
private NavMeshAgent agent;
public Transform[] patrolPoints;
private int currentPoint = 0;
void Start()
{
agent = GetComponent<NavMeshAgent>();
MoveToNextPoint();
}
void Update()
{
if (!agent.pathPending && agent.remainingDistance < 0.5f)
{
MoveToNextPoint();
}
}
void MoveToNextPoint()
{
if (patrolPoints.Length == 0) return;
agent.SetDestination(patrolPoints[currentPoint].position);
currentPoint = (currentPoint + 1) % patrolPoints.Length;
}
void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
Debug.Log("Interacted with Player");
// 播放动画或触发对话
}
}
}
总结
Unity的3D场景制作需要整合模型、动画、导航、物理等多个模块,以下是制作流程的关键点:
<