Unity小白也能搞定的原神桌宠:从PMX模型到可拖拽交互的完整实现(附避坑点)

张开发
2026/4/12 3:34:27 15 分钟阅读

分享文章

Unity小白也能搞定的原神桌宠:从PMX模型到可拖拽交互的完整实现(附避坑点)
Unity小白也能搞定的原神桌宠从PMX模型到可拖拽交互的完整实现附避坑点1. 准备工作与环境搭建作为一个Unity初学者想要制作一个原神风格的桌宠首先需要准备好必要的工具和环境。这个过程可能会让新手感到有些迷茫但只要按照步骤来其实并不复杂。必备工具清单Unity Hub Unity编辑器推荐2021 LTS版本Blender 2.93或更高版本原神PMX模型文件可以从一些模型分享网站获取一个简单的代码编辑器如VS Code安装Unity时建议选择以下模块Windows/Mac Build Support根据你的操作系统Android Build Support可选如果你想让桌宠也能在手机上运行Unity Collaborate方便版本控制Blender的安装相对简单但需要注意一点安装完成后需要额外安装MMD Tools插件这个插件可以帮助我们处理PMX格式的模型文件。安装方法也很简单下载MMD Tools插件在Blender的Edit Preferences Add-ons中点击Install选择下载的插件文件并启用提示Blender 2.93版本对PMX模型的支持较好建议使用这个版本以避免兼容性问题。2. 模型转换与导入2.1 PMX到FBX的转换拿到PMX模型后我们需要将其转换为Unity能够识别的FBX格式。这个过程在Blender中完成打开Blender删除默认的立方体点击File Import MMD Model(.pmd/.pmx)选择你的原神PMX模型文件导入后在右侧属性面板中找到Armature选项勾选Auto IK和Leg IK取消勾选Keep Upper Chest点击File Export FBX这里有几个关键点需要注意Keep Upper Chest选项如果不取消勾选模型脖子部位的骨骼可能会出现异常折叠缩放设置建议将FBX导出设置中的缩放设为0.01这样导入Unity后模型大小会比较合适动画导出如果你需要导出动画记得勾选Bake Animations2.2 Unity中的模型导入将FBX文件导入Unity后还需要进行一些设置才能让模型正常工作在Project窗口中选择导入的FBX文件在Inspector窗口中找到Rig选项卡将Animation Type设置为Humanoid点击Configure按钮检查骨骼映射是否正确在Materials选项卡中勾选Use External Materials如果一切顺利你应该能在场景中看到你的原神角色模型了。如果模型显示为紫色说明材质丢失需要手动重新指定材质。3. 动画系统配置3.1 基础动画设置为了让桌宠能够动起来我们需要配置Unity的Animator系统在Project窗口中右键创建 Animator Controller将创建好的Animator Controller拖到场景中的模型上双击Animator Controller打开Animator窗口从Mixamo等网站下载一些基础动画如站立、挥手等将动画FBX文件拖入Animator窗口一个简单的动画状态机可以这样设置创建两个状态Idle和Wave创建一个Bool类型的参数isWaving设置从Idle到Wave的过渡条件为isWaving为true设置从Wave到Idle的过渡条件为isWaving为false3.2 动画切换控制通过代码控制动画切换非常简单using UnityEngine; public class PetController : MonoBehaviour { private Animator animator; private bool isWaving false; void Start() { animator GetComponentAnimator(); } void Update() { if (Input.GetMouseButtonDown(0)) { isWaving !isWaving; animator.SetBool(isWaving, isWaving); } } }这段代码会让角色在鼠标左键点击时切换站立和挥手动画。4. 交互功能实现4.1 拖拽功能实现桌宠的拖拽功能有几种方法这里介绍最稳定的一种using UnityEngine; using UnityEngine.EventSystems; public class DragHandler : MonoBehaviour, IDragHandler { private RectTransform rectTransform; private Canvas canvas; void Start() { rectTransform GetComponentRectTransform(); canvas GetComponentInParentCanvas(); } public void OnDrag(PointerEventData eventData) { rectTransform.anchoredPosition eventData.delta / canvas.scaleFactor; } }这种方法通过UI事件系统实现性能较好且不容易出现拖拽卡顿的问题。使用时需要注意给模型添加Canvas Group组件设置Canvas的Render Mode为Screen Space - Overlay调整模型的RectTransform大小和位置4.2 旋转功能右键旋转桌宠的实现也很简单using UnityEngine; public class RotateHandler : MonoBehaviour { public float rotationSpeed 10f; void Update() { if (Input.GetMouseButton(1)) { float rotX Input.GetAxis(Mouse X) * rotationSpeed; transform.Rotate(Vector3.up, -rotX, Space.World); } } }4.3 点击交互除了基本的拖拽和旋转我们还可以为桌宠添加一些有趣的点击反馈using UnityEngine; public class ClickHandler : MonoBehaviour { public ParticleSystem heartEffect; void OnMouseDown() { if (heartEffect ! null) { heartEffect.Play(); } // 可以在这里添加其他反馈效果 } }5. 视觉效果优化5.1 卡通渲染为了让原神角色保持其标志性的卡通风格我们需要设置特殊的着色器在Asset Store中搜索Toon Shader并导入为模型材质选择卡通着色器调整边缘光(rim light)参数设置适当的阴影颜色5.2 背景透明实现窗口透明需要一些特殊设置在Player Settings中找到Resolution and Presentation勾选Use DXGI Flip Model Swapchain仅Windows创建如下脚本并附加到主相机using UnityEngine; [RequireComponent(typeof(Camera))] public class TransparentWindow : MonoBehaviour { void Start() { Camera.main.backgroundColor new Color(0, 0, 0, 0); Camera.main.clearFlags CameraClearFlags.SolidColor; } }5.3 抗锯齿处理解决模型边缘锯齿问题在Quality Settings中开启MSAA 4x或8x或者使用后处理抗锯齿如SMAA6. 常见问题与解决方案在实际开发过程中可能会遇到以下问题模型导入后变形检查Blender导出设置确保Unity中的缩放系数正确验证骨骼映射是否准确动画播放不正常检查Animator Controller中的状态机设置确认动画剪辑是否正确地导入查看模型是否正确地标记为Humanoid拖拽卡顿尝试降低拖拽更新的频率使用更高效的拖拽实现方式检查是否有其他脚本在占用大量CPU资源透明背景显示异常确保使用的是支持透明的着色器检查相机的清除标志设置在Windows平台上可能需要特殊的项目设置7. 进阶功能扩展完成基础功能后可以考虑添加一些更有趣的特性自动寻路使用Unity的NavMesh系统让桌宠在屏幕上自动移动设置几个固定的巡逻点表情变化通过材质球切换实现不同的面部表情或者使用Blend Shape控制面部变化互动反馈添加音效反馈实现粒子特效记录用户互动频率并做出不同反应多平台支持打包为Windows桌面应用适配移动端触摸交互考虑WebGL版本// 简单的自动寻路示例 using UnityEngine; using UnityEngine.AI; public class PetAI : MonoBehaviour { public Transform[] waypoints; private NavMeshAgent agent; private int currentWaypoint 0; void Start() { agent GetComponentNavMeshAgent(); GoToNextWaypoint(); } void GoToNextWaypoint() { if (waypoints.Length 0) return; agent.destination waypoints[currentWaypoint].position; currentWaypoint (currentWaypoint 1) % waypoints.Length; } void Update() { if (!agent.pathPending agent.remainingDistance 0.5f) { GoToNextWaypoint(); } } }8. 性能优化建议随着功能增加需要注意保持应用的流畅性渲染优化使用GPU Instancing合并材质球减少实时阴影脚本优化避免在Update中做复杂计算使用对象池管理特效合理使用协程内存管理及时销毁不再需要的对象使用Addressable Asset System管理资源监控内存泄漏多线程考虑将部分计算移到Job System使用Burst Compiler优化数学运算注意在开发过程中建议定期使用Unity的Profiler工具检查性能瓶颈。

更多文章