第7章 移动端角色资产全流程:《暗黑王朝》主角与敌人的建模、贴图及动画

在《暗黑王朝》这样一款写实风格的射击手游中,角色是玩家情感的投射点,也是视觉体验的核心。一个令人印象深刻的游戏角色,需要经过概念设计、模型构建、贴图绘制、骨骼绑定、动画调节等一系列复杂工序,最终在Unity中组装成可操控的游戏实体。本章将跟随《暗黑王朝》的开发流程,从主角的定位分析开始,逐步展开模型制作、贴图绘制、骨骼动画的完整技术链条,并针对远程和近战两类敌人分别讲解其设计要点,最后将所有资产导入Unity并进行动画分割与场景布置。

7.1 游戏主角的完整构建流程

7.1.1 角色的特性分析与定位

在开始动手建模之前,首先要回答一个问题:这个角色是谁?在《暗黑王朝》的世界观中,主角是一名精英特种部队指挥官,代号"夜隼",被派遣到被暗物质感染的禁区执行调查任务。这一角色定位直接决定了后续的所有设计决策:

视觉特征:现代军事风格,装备高科技战术装备,轮廓鲜明,便于在复杂场景中快速识别。主角的剪影应该具有辨识度——战术头盔、肩部护甲、贴身作战服,这些元素构成了玩家一眼就能认出的轮廓。

功能需求:作为射击游戏的主角,需要支持多种武器切换、战术动作(翻滚、掩体射击)、近战攻击等。这要求模型的关节部位(肩、肘、膝)有合理的拓扑结构,确保动画变形自然。

面数预算:根据移动平台的性能限制,主角作为屏幕上的核心角色,面数可以适当放宽,但必须控制在8000-10000面以内,纹理尺寸不超过2048x2048。按照行业标准,移动设备每个网格模型控制在300-1500个多边形能达到较好效果,但主角作为特殊存在可以适当提高。

7.1.2 使用Maya建立主角模型

在Maya中建立角色模型,遵循从整体到局部的原则。根据三维建模的行业实践,建模过程通常分为原型搭建、拓扑优化、细节雕刻、UV拆分四个阶段。

原型搭建阶段:从基本几何体(立方体、圆柱体)开始,通过挤出(Extrude)、倒角(Bevel)等操作建立角色的基础比例。在《暗黑王朝》主角的建模中,我们首先确定角色高度约为8个头长,符合写实人体的比例。使用"图片平面"功能将概念图导入作为参考,确保各视图比例一致。

拓扑优化阶段:使用Multi-Cut工具进行结构线重分布。关节部位(肩、肘、膝)需要至少3条环线以确保动画变形平滑,而肌肉发达的区域(胸、背、大腿)需要更密集的布线来表现体积感。遵循"四边面优先"原则,尽量避免三角面和N-gon。

细节雕刻阶段:在基础模型完成后,使用Sculpt Geometry Tool雕刻肌肉纹理等微观形态。对于写实风格角色,肌肉的起止点、肌腱的隆起都需要准确表现。但要注意,过于精细的雕刻会增加面数,因此细节主要通过法线贴图来实现。

UV拆分阶段:这是连接模型与贴图的关键环节。需要将模型表面解构为二维平面,确保UV接缝处理自然,避免贴图拉伸变形。在制作人物面部时,需将眼部、鼻部等细节区域单独划分UV块,以提升纹理精度。UV布局应充分利用0-1空间,尽量减少浪费。

在《暗黑王朝》的开发中,我们为角色设定了三个LOD级别:LOD0用于近距离特写,面数约10000;LOD1用于中等距离,面数约5000;LOD2用于远距离,面数约2000。这种多级LOD策略可以确保在不同视距下都能获得最佳的性能表现。

7.1.3 利用Photoshop绘制PBR材质贴图

模型完成后,需要在Photoshop中绘制贴图,赋予角色真实的质感。次世代游戏角色通常需要多通道贴图:固有色贴图、法线贴图、粗糙度贴图、金属度贴图、环境光遮蔽贴图。

UV模板的导出与导入:在Maya中导出UV模板(通常为PNG格式),该模板作为PS中的绘制基准。模板需包含清晰的UV边界线,便于在PS中精准定位纹理区域。在《暗黑王朝》主角的盔甲部分,多个独立部件需分别对应不同的金属质感贴图。

固有色贴图的绘制:固有色贴图定义了材质的基色。对于写实角色,应避免使用纯色,而是通过叠加多种纹理创造丰富的视觉效果。例如,作战服的布料纹理可以使用真实布料扫描图叠加噪点,增强表面粗糙感;金属盔甲可以采用银灰色渐变配合划痕图层,模拟使用痕迹。

法线贴图的生成:法线贴图通过RGB通道存储表面法线方向信息,使低模在光照下呈现高模的细节。在PS中,可以通过"滤镜>3D>生成凹凸图"将灰度图转换为法线贴图。例如,制作作战服的编织纹理时,可将编织图案的黑白图转化为法线数据。对于复杂细节,可以使用XNormal或Maya内置的Transfer Maps功能从高模烘焙。

粗糙度与金属度贴图:这两张贴图控制材质的物理反射特性。金属度贴图中,金属部分为白色,非金属部分为黑色;粗糙度贴图中,光滑表面为黑色(如枪械金属),粗糙表面为白色(如作战服布料)。在《暗黑王朝》主角的装备中,武器和护甲配件需要精细的金属度控制,而作战服则保持非金属特性。

环境光遮蔽贴图的烘焙:AO贴图模拟了环境光被几何遮挡产生的阴影,可以显著增强模型的立体感。在Maya中可以使用Transfer Maps功能烘焙,也可以在PS中通过图层样式叠加。AO贴图通常作为混合层叠加在固有色贴图上,或作为单独通道输入材质系统。

7.1.4 骨骼动画系统的建立

贴图完成后,需要为角色建立骨骼系统,这是让模型"活起来"的关键步骤。Maya动画绑定工具集(ART)提供了一套综合性的工具,能够处理角色骨架创建、骨架放置和绑定创建。

骨骼结构的搭建:对于二足人形角色,骨骼通常包含脊椎(3-5节)、颈部、头部、锁骨、手臂(上臂、前臂、手)、腿部(大腿、小腿、脚)以及手指骨骼。在《暗黑王朝》主角的绑定中,我们采用了标准的人形骨骼结构,关节处适当增加骨骼以支持更自然的弯曲。

IK/FK切换系统的设置:手臂和腿部通常需要同时支持正向动力学和反向动力学。FK模式适合弧线运动(如挥手),IK模式适合需要固定终点位置的运动(如脚部着地)。在Maya中,通过设置IK Handle和约束,可以创建可切换的IK/FK系统。

蒙皮权重绘制:将模型绑定到骨骼后,需要绘制蒙皮权重,控制每个骨骼对模型顶点的影响程度。权重绘制的质量直接影响动画变形的自然度。关节区域通常需要多个骨骼共同影响,以实现平滑过渡。在《暗黑王朝》的开发中,肘关节和膝关节的权重绘制特别精细,避免出现"蝴蝶折"式的生硬变形。

7.1.5 游戏专用分帧动画的调节

骨骼绑定完成后,需要为角色调节游戏所需的各类动画。移动端游戏动画有严格的帧率和面数要求,动画帧率一般控制在24-30FPS即可。

核心动画集:游戏角色必须包含以下基础动画:

  • Idle待机:角色静止时的微动状态,包括呼吸、身体轻微晃动,营造"活着的"感觉
  • Run/Walk走跑:根据游戏节奏设置不同速度的移动动画
  • Jump跳跃:包括起跳、空中滞留、落地三个阶段
  • Attack攻击:根据武器类型设计不同的攻击动作
  • Hurt受击:受到攻击时的反应动作
  • Death死亡:角色倒下的完整过程

动作表现力的强化:移动端屏幕小、细节不易辨认,因此动画动作可以适当夸张以提高辨识度。在《暗黑王朝》主角的奔跑动画中,我们刻意加大手臂摆动幅度和身体前倾角度,让玩家即使在小屏幕上也能清晰识别移动状态。同时,强调关键动作姿态,善用预备动作和跟随动作增加表现力。

循环动画的处理:Idle、Run等需要流畅循环无缝衔接的动画,必须确保首尾帧过渡自然。在Maya中,可以通过Graph Editor调整动画曲线,使循环点处的速度和加速度连续。

7.2 远距离攻击敌人的设计与制作

7.2.1 远程敌人模型的特点与构建

在《暗黑王朝》中,远距离攻击敌人被设计为"潜伏者"——一种被感染后获得隐身能力的变异生物,擅长从暗处偷袭玩家。这类敌人的设计重点在于辨识度和视觉引导。

面数控制:作为次要角色,远程敌人的面数应低于主角,控制在3000-4000面。根据行业规范,移动设备每个网格模型控制在300-1500个多边形能达到较好的效果,但精英敌人可以适当提高。

轮廓设计:远程敌人需要在远处就能被识别,因此轮廓要鲜明。我们为"潜伏者"设计了修长的四肢、驼背的体态、发光的眼睛——即使在50米外,玩家也能一眼认出这是威胁。

关键部位强化:远程攻击手段通常是投射物,因此手臂和眼睛是需要重点表现的部位。我们为"潜伏者"的右臂设计了夸张的变异结构,投掷动作时特别醒目。

7.2.2 Photoshop贴图绘制的差异化策略

远程敌人的贴图需要强调"潜行"和"变异"的主题。在Photoshop中绘制时,采用以下策略:

固有色贴图:以深灰、暗紫色调为主,使敌人在暗处不易被发现。但眼睛和能量核心部位使用高饱和度颜色,形成视觉焦点。通过图层样式中的"外发光"效果,为能量核心区域添加自发光感。

法线贴图:强化皮肤变异纹理,模拟鳞片、皱褶等细节。可以使用真实生物纹理(如蜥蜴皮肤)作为素材,通过叠加和变形适配到UV区域。

自发光贴图:为眼睛和能量核心区域单独制作自发光通道,在Unity中实现夜晚发光的视觉效果,帮助玩家定位敌人位置。

7.2.3 骨骼与分帧动画设计

远程敌人的动画强调"隐匿"和"突然袭击"的节奏感:

待机动画:半透明的身体若隐若现,轻微移动,模拟潜行状态。使用正弦波控制透明度变化,周期设为3-5秒。

攻击动画:投掷动作分为三个阶段——预备(蓄力)、释放(快速投掷)、恢复(后退)。预备阶段占40%时间,让玩家有反应时间;释放阶段仅占20%,体现速度感。

移动动画:采用诡异的爬行姿态,四肢交替前进,身体贴地。动画速度较慢,但步伐节奏不规则,增加压迫感。

7.3 近距离攻击敌人的设计与制作

7.3.1 近战敌人模型的特点与构建

近距离攻击敌人被设计为"狂暴者"——一种体型庞大、力量惊人但行动迟缓的变异生物,一旦接近玩家将造成巨大威胁。

面数控制:同样控制在3000-4000面,但面数分布侧重上肢和头部,因为这些部位是攻击时玩家关注的重点。

体型设计:采用倒三角形体型,肩部异常宽厚,手臂粗壮,头部相对较小。这种设计强化了力量感,也使攻击判定范围更加直观。

关键部位强化:手掌和牙齿是需要重点表现的部位,因为这是近战攻击的主要手段。手掌的每个指节都保持合理的拓扑结构,确保抓取动作时变形自然。

7.3.2 Photoshop贴图绘制的差异化策略

近战敌人的贴图需要强调"厚重"和"伤痕累累"的质感:

固有色贴图:以深褐色为主,模拟泥土和血迹的混合。使用"颗粒画笔"快速生成划痕、血迹等磨损效果。在肘部、膝盖等经常接触地面的部位添加磨损高光。

粗糙度贴图:全身保持较高的粗糙度(白色),只有牙齿和爪子等硬质部分降低粗糙度(深灰色)。这种设计使敌人在光照下呈现暗淡的质感,突出其"土生土长"的感觉。

AO贴图:通过增强环境光遮蔽效果,强化肌肉之间的缝隙和伤口凹陷,使模型看起来更加沧桑和恐怖。

7.3.3 骨骼与分帧动画设计

近战敌人的动画强调"力量感"和"压迫感":

待机动画:身体沉重地起伏,伴随低沉的呼吸声,头部缓慢转动锁定玩家。动画幅度小而重量感强,表现其庞大的体型。

攻击动画:重击动作分为三个阶段——高举手臂(预备)、猛力砸下(攻击)、拔出武器(恢复)。整个动作时长约1.5秒,较慢但威力巨大。通过缓入缓出的动画曲线,表现肌肉用力的过程。

受击动画:受到攻击时短暂停顿,但不会后退,体现其顽强的生命力。只有在累计一定伤害后才会踉跄,最终轰然倒地。

7.4 基于Unity的模型与动画导出

7.4.1 Maya到FBX的导出规范

所有模型和动画在Maya中制作完成后,需要导出为FBX格式,这是Unity支持的通用三维交换格式。导出时需要遵循以下规范:

模型导出设置

  • 选择File > Export Selection
  • 在FBX Export选项中,设置以下参数:
    • Include:选择Smoothing Groups和Smooth Mesh(如果需要在导出时细分)
    • Geometry:勾选Triangulate(Unity接受三角面),取消勾选Convert to Null Objects
    • Animation:根据是否包含动画决定勾选
    • Units:设置为Centimeters或Meters,与Unity项目单位一致
    • Axis Conversion:选择Y轴向上,这是Unity的坐标系

命名规范:根据行业规范,角色模型命名格式为"People_角色名字",角色模型动画命名格式为"People_角色名字@动画名"。例如,主角的待机动画命名为"People_NightHawk@Idle"。

整理文件:导出前,务必整理Maya场景,删除没有用的一切物件,合并断开的顶点,移除孤立的顶点。这些冗余数据会增大FBX文件体积,影响Unity导入效率。

7.4.2 Unity中的动画分割与Avatar配置

将FBX文件导入Unity后,需要进行动画分割和Avatar配置,让动画系统能够正确识别和使用动画数据。

Avatar配置:根据Unity官方文档,导入带有人形动画的模型时,需要将模型的骨骼结构映射到人形Avatar上。

  1. 选中导入的模型,在Inspector中打开Rig选项卡
  2. 将Animation Type设置为Humanoid
  3. 点击Apply,Unity会尝试自动匹配骨骼
  4. 如果匹配失败,点击Configure按钮进入Avatar配置模式,手动分配骨骼
  5. 确保模型处于T形姿势,如果姿势不正确,选择Pose > Enforce T-Pose修复

动画分割:如果一个FBX文件包含多个动画剪辑(如Idle、Run、Attack连续排列),需要在Animation选项卡中进行分割。

  1. 在Animation选项卡中,勾选Import Animation
  2. 在Clips列表中,点击加号创建新剪辑
  3. 设置剪辑的Start和End帧,命名(如Idle、Run)
  4. 勾选Loop Time,确保循环动画无缝衔接
  5. 对于需要完美循环的动画,可勾选Loop Pose让首尾帧匹配更自然

Avatar遮罩的应用:如果需要在某些层只播放特定骨骼的动画(如上半身武器瞄准),可以创建Avatar Mask资源。

  1. 在Project窗口右键,选择Create > Avatar Mask
  2. 在Inspector中,选择需要启用的骨骼(如只保留上半身)
  3. 将该遮罩应用于Animator Controller中对应层的Mask属性

7.4.3 角色模型在场景中的组装

动画分割完成后,需要将角色模型放置于场景,并组装完整的角色控制器。

创建角色预制体

  1. 将模型文件从Project窗口拖入场景
  2. 添加必要的组件:Animator、Character Controller(或自定义控制器)、Audio Source等
  3. 调整模型位置,确保脚部接触地面
  4. 拖回Project窗口创建预制体,便于后续复用

Animator Controller的配置

  1. 在Project窗口右键,创建Animator Controller
  2. 双击打开Animator窗口
  3. 将分割好的动画剪辑拖入窗口
  4. 设置参数(如Float类型的"Speed")控制动画切换
  5. 创建动画状态之间的过渡(Transition),设置切换条件
  6. 将Animator Controller赋值给角色的Animator组件

以下是一个完整的角色动画控制脚本示例:

using UnityEngine;

namespace DarkOrder.Character
{
    /// <summary>
    /// 角色动画控制器 - 控制主角动画状态切换
    /// </summary>
    [RequireComponent(typeof(Animator))]
    public class CharacterAnimationController : MonoBehaviour
    {
        [Header("组件引用")]
        [SerializeField] 
        private Animator m_Animator;
        
        [SerializeField] 
        private CharacterController m_CharacterController;
        
        [Header("动画参数名称")]
        [SerializeField] 
        private string m_SpeedParameter = "Speed";
        
        [SerializeField] 
        private string m_IsGroundedParameter = "IsGrounded";
        
        [SerializeField] 
        private string m_VerticalSpeedParameter = "VerticalSpeed";
        
        [SerializeField] 
        private string m_AttackTrigger = "Attack";
        
        [SerializeField] 
        private string m_HurtTrigger = "Hurt";
        
        [SerializeField] 
        private string m_DeathTrigger = "Death";
        
        // 运动状态
        private Vector3 m_PreviousPosition;
        private float m_CurrentSpeed;
        
        private void Awake()
        {
            if (m_Animator == null)
            {
                m_Animator = GetComponent<Animator>();
            }
            
            if (m_CharacterController == null)
            {
                m_CharacterController = GetComponent<CharacterController>();
            }
            
            m_PreviousPosition = transform.position;
        }
        
        private void Update()
        {
            UpdateMovementParameters();
        }
        
        /// <summary>
        /// 更新移动相关参数
        /// </summary>
        private void UpdateMovementParameters()
        {
            // 计算水平速度
            Vector3 currentPosition = transform.position;
            Vector3 deltaPosition = currentPosition - m_PreviousPosition;
            deltaPosition.y = 0; // 忽略垂直速度
            
            float distance = deltaPosition.magnitude;
            m_CurrentSpeed = distance / Time.deltaTime;
            
            // 设置速度参数
            m_Animator.SetFloat(m_SpeedParameter, m_CurrentSpeed);
            
            // 设置接地状态
            bool isGrounded = m_CharacterController.isGrounded;
            m_Animator.SetBool(m_IsGroundedParameter, isGrounded);
            
            // 设置垂直速度(用于跳跃/下落动画)
            float verticalSpeed = (currentPosition.y - m_PreviousPosition.y) / Time.deltaTime;
            m_Animator.SetFloat(m_VerticalSpeedParameter, verticalSpeed);
            
            m_PreviousPosition = currentPosition;
        }
        
        /// <summary>
        /// 触发攻击动画
        /// </summary>
        public void TriggerAttack()
        {
            m_Animator.SetTrigger(m_AttackTrigger);
        }
        
        /// <summary>
        /// 触发受击动画
        /// </summary>
        public void TriggerHurt()
        {
            m_Animator.SetTrigger(m_HurtTrigger);
        }
        
        /// <summary>
        /// 触发死亡动画
        /// </summary>
        public void TriggerDeath()
        {
            m_Animator.SetTrigger(m_DeathTrigger);
        }
        
        /// <summary>
        /// 动画事件回调 - 由动画剪辑调用
        /// </summary>
        public void OnAttackHit()
        {
            // 在攻击动画的特定帧调用,处理伤害判定
            Debug.Log("攻击命中帧");
            // 触发武器碰撞检测等逻辑
        }
        
        /// <summary>
        /// 动画事件回调 - 由动画剪辑调用
        /// </summary>
        public void OnFootstep()
        {
            // 在脚步声响起时调用,播放脚步声效
            Debug.Log("脚步声");
        }
    }
}

对于敌人角色的控制,可以继承上述基类并根据需要重写或扩展功能:

using UnityEngine;

namespace DarkOrder.AI
{
    /// <summary>
    /// 敌人动画控制器 - 继承角色动画控制器并扩展AI相关功能
    /// </summary>
    public class EnemyAnimationController : CharacterAnimationController
    {
        [Header("敌人特有参数")]
        [SerializeField] 
        private string m_AlertedParameter = "IsAlerted";
        
        [SerializeField] 
        private string m_AttackTypeParameter = "AttackType";
        
        private EnemyAIController m_EnemyAI;
        
        protected override void Awake()
        {
            base.Awake();
            m_EnemyAI = GetComponent<EnemyAIController>();
        }
        
        private void Update()
        {
            // 调用基类更新移动参数
            // 注意:这里不能直接调用base.Update(),因为我们需要自定义更新逻辑
            // 实际项目中应考虑使用事件驱动或状态机模式
            
            // 更新敌人特有状态
            if (m_EnemyAI != null)
            {
                // 根据AI状态设置动画参数
                m_Animator.SetBool(m_AlertedParameter, m_EnemyAI.IsAlerted);
                m_Animator.SetInteger(m_AttackTypeParameter, m_EnemyAI.GetAttackType());
            }
        }
    }
}

7.5 角色资产的性能优化与测试

7.5.1 模型面数与纹理的最终检查

将所有角色资产导入Unity后,需要进行全面的性能检查和优化:

面数统计:使用Profiler或自定义工具统计场景中角色的总三角面数。根据《暗黑王朝》的测试,单个场景同时出现的角色不应超过10个,总面数控制在5万面以内,才能保证30FPS的流畅运行。

纹理内存估算:每张2048x2048的纹理在内存中约占16MB(压缩后约4-8MB)。一个完整的角色通常需要4-6张贴图(Albedo, Normal, Metallic, AO, Emission),内存占用约30-50MB。必须严格控制同时加载的角色数量。

Draw Call统计:每个使用不同材质的角色会增加一个Draw Call。通过纹理集合并材质,尽可能让多个角色共用材质,可以有效降低Draw Call。

7.5.2 动画性能的测试要点

动画系统的性能问题通常表现为CPU耗时过高。以下是《暗黑王朝》项目中的测试要点:

骨骼数量控制:每个角色的骨骼数量不应超过60个。过多的骨骼会增加动画计算的开销。对于不需要独立控制的部位(如手指),可以考虑使用代理骨骼或简化骨骼结构。

动画文件大小:过长的动画文件会增加内存占用。确保动画剪辑只包含必要的帧,并开启Keyframe Reduction压缩。

Animator Update频率:对于远离相机的角色,可以降低Animator的更新频率。通过设置Animator组件的更新模式(Normal, Animate Physics, Unscaled Time)或在代码中控制更新间隔。

7.5.3 多角色同时渲染的优化策略

当场景中需要同时出现多个角色时,需要采用特殊的优化手段:

GPU Instancing:对于相同类型的敌人,使用GPU Instancing技术批量渲染。需要确保这些敌人共用相同的网格和材质。

LOD系统的应用:为每个角色配置2-3个LOD级别。根据行业规范,LM (Low Model)级别模型面数可降低至500面以下。LOD切换距离需根据场景规模精心调整,既要保证视觉质量,又要确保性能。

遮挡剔除:在场景中合理放置遮挡物,设置Occlusion Culling,让被墙壁遮挡的角色不参与渲染。这是提升CPU性能的有效手段。

7.6 本章小结

本章围绕《暗黑王朝》的角色资产制作,系统讲解了从概念定位到最终Unity集成的完整流程。在主角制作部分,我们详细阐述了Maya建模、PS贴图绘制、骨骼绑定、动画调节的每一个环节,强调了移动平台特有的性能约束——面数控制、纹理大小、骨骼数量。

远程和近战两类敌人的设计展示了角色差异化的重要性:远程敌人强调视觉辨识度和偷袭感,近战敌人强调力量感和压迫感。通过贴图策略和动画节奏的调整,同一套技术流程可以创造出性格迥异的游戏角色。

FBX导出和Unity集成是连接三维软件和游戏引擎的桥梁。本章详细介绍了导出设置、Avatar配置、动画分割的技术要点,并提供了完整的动画控制器代码示例。这些实践经验直接来源于《暗黑王朝》的项目开发,具有较强的实战参考价值。

最后,我们强调了角色资产的性能优化问题。在移动平台上,艺术表现力必须与技术可行性平衡。通过严格的面数控制、纹理压缩、LOD分层、遮挡剔除等手段,可以在有限的硬件资源内创造出丰富的角色阵容。

成功的游戏角色设计,是艺术表达与技术约束的完美平衡。设计师必须在吸引玩家的视觉魅力与流畅运行的性能要求之间找到最佳契合点。从概念到骨骼,从贴图到动画,每一环节都需要精雕细琢,才能最终让角色成为玩家在游戏世界中的完美化身。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐