第三人称——骑马系统以及交互动画

作者:神龙天舞2001日期:2026/8/3

第三人称——骑马系统以及交互动画

大家好,今天我们来聊一个在游戏开发里特别有“内味儿”的话题——第三人称视角下的骑马系统,以及那些让玩家觉得“哇,这马好听话”的交互动画。骑马不是简单的“把角色模型放到马背上”,它涉及到动画状态机、物理交互、摄像机跟随、甚至还有“骑手重心偏移”这种细节。这篇文章我会用最接地气的方式,把核心逻辑拆开揉碎,配上能跑的代码示例,让你看完就能上手做原型。## 一、骑马系统的核心:不是“骑上去”,而是“合体”很多新手做骑马,就是把玩家角色(Humanoid)的骨骼绑定到马(Quadruped)的骨架上,然后播放一个“骑乘”动画。但这样会出现两个致命问题:1. 角色脚会穿模进马肚子。2. 马转弯时,角色身体像根棍子一样直挺挺的,毫无跟随感。真正的骑马系统,要处理的是 “骑手与马匹的复合运动” 。也就是说,马是“根运动体”,骑手是“依附体”,但骑手的动画要能独立播放(比如挥手、射箭),同时又要跟随马的起伏、转向。这通常用 “IK(反向动力学)定位” 和 “动画分层” 来解决。### 1. 动画分层:上半身和下半身分开在Unity或虚幻里,我们常用Animator的Layer机制。Layer 0(Base Layer)播放马的跑步循环;Layer 1(UpperBody)播放骑手的待机或攻击动作,并设置 Avatar Mask 只影响上半身骨骼。csharp// Unity C# 示例:设置骑马时的动画层权重using UnityEngine;public class HorseRiderAnimator : MonoBehaviour{ public Animator riderAnimator; // 骑手的Animator public Animator horseAnimator; // 马的Animator,通常挂在马模型上 void Start() { // 开启上层动画(比如“骑射”层),权重从0渐变到1,实现平滑过渡 riderAnimator.SetLayerWeight(1, 1f); // 设置骑手动画的“马匹速度”参数,让上下半身动画速度匹配 riderAnimator.SetFloat("HorseSpeed", 1f); } void Update() { // 从马匹动画状态机里读取当前速度(假设马自己有Movement脚本) float horseSpeed = horseAnimator.GetFloat("Speed"); riderAnimator.SetFloat("HorseSpeed", horseSpeed); // 同步马匹的转向角度给骑手,让骑手的上半身能稍微倾斜(如果动画里有转弯倾斜) float turnAngle = horseAnimator.GetFloat("TurnAngle"); riderAnimator.SetFloat("TurnAngle", turnAngle); }}这段代码的核心就是“参数同步”——骑手的动画完全由马的动画状态驱动,但通过LayerMask隔离了上半身,这样你可以在骑马时自由攻击或举盾。### 2. 骑手骨骼对齐:别让屁股悬空如果你的马模型和骑手模型不是同一个DCC工具里做的,骨骼位置肯定对不上。这时候就需要在运行时做 “骨骼重定向”。简单做法是:在马的背脊上放几个空物体(Empty GameObject)作为“骑乘锚点”,然后用脚本把骑手的骨盆(Hips)位置每帧强制对齐到锚点。csharp// Unity C# 示例:将骑手骨盆对齐到马背锚点,并保持腿部IKusing UnityEngine;public class RiderSeat : MonoBehaviour{ public Transform horseSpineAnchor; // 马背上的锚点(空物体) public Transform riderHips; // 骑手的骨盆骨骼 public float heightOffset = 0.1f; // 调整臀部离马背的高度,避免穿模 void LateUpdate() { // 先将骑手骨盆移动到锚点上方,并保持世界旋转一致 riderHips.position = horseSpineAnchor.position + Vector3.up * heightOffset; riderHips.rotation = horseSpineAnchor.rotation; // 这里可以调用IK脚本,让骑手的脚自动寻找马镫位置 // 如果腿部有IK目标,可以在这里更新目标位置 }}注意:LateUpdate 很重要,因为动画系统在 Update 里更新骨骼,我们在 LateUpdate 里覆盖位置,能保证最终渲染时是正确姿势。## 二、交互动画:从“按E上马”到“丝滑无缝”骑马的交互动画,不只是“播放一个上马动画”。玩家从地面走到马旁,按E,然后角色要走到正确的位置、转向、跳起、跨坐。这一串动作如果直接硬切,玩家会觉得“我是瞬移上去的吗?” 所以我们需要做一个 “交互状态机”。### 1. 交互触发:位置与朝向的匹配首先,你得在马的侧面定义几个“上马点”(MountPoint)。当玩家按E时,系统会找到最近的、且朝前的上马点,然后让玩家播放“走到点并转身”的动画。这里有个小技巧:使用 Root Motion(根运动)可以让动画自带位移,而不是靠代码移动。python# 伪代码示例(Unity C# 类似,但这里用Python风格说明逻辑)def try_mount(player, horse): mount_points = horse.get_mount_points() # 返回马左右两侧的Transform列表 nearest = find_nearest_mount_point(player.position, mount_points) if nearest is None: return False # 检查玩家是否朝向马(点积判断) player_forward = player.get_forward() to_mount_dir = (nearest.position - player.position).normalized if Vector3.Dot(player_forward, to_mount_dir) > 0.3: # 播放“走向马”的动画,动画自带位移,到达后触发“上马”事件 player.play_animation("walk_to_mount", on_finish=lambda: start_mount_sequence(player, horse)) return True return False这里的关键是 walk_to_mount 动画要设计好——它应该是一个“走到马侧并转身面对马”的单次播放动画,并且开启Root Motion,这样角色会自己移动到位。### 2. 上马动画的“瞬移”处理现实中,上马是一个连续动作,但游戏里如果每次都要精确匹配,容易出Bug(比如马在动)。所以常用做法是:播放上马动画的瞬间,将玩家控制器禁用,然后直接 “吸附” 到马鞍位置,并播放一个 “上马过渡动画”(比如一个快速抬腿跨坐的0.3秒动画)。csharp// Unity C# 示例:上马时的位置吸附与临时控制权转移using UnityEngine;public class MountInteraction : MonoBehaviour{ public Transform mountAnchor; // 马鞍锚点 public GameObject playerController; // 玩家控制脚本(用于禁用) public Animator playerAnimator; public string mountAnimName = "Mount_Horse"; public void StartMount() { // 1. 禁用玩家移动控制和摄像机跟随(防止玩家乱动) playerController.SetActive(false); // 2. 将玩家位置和旋转直接对齐到锚点 transform.position = mountAnchor.position; transform.rotation = mountAnchor.rotation; // 3. 播放上马动画(如果动画是“跨坐”,可以设置为InPlace,不产生位移) playerAnimator.CrossFade(mountAnimName, 0.1f); // 4. 在动画事件中(或延迟调用)重新启用控制,但切换到骑马模式 Invoke(nameof(FinishMount), 0.5f); } void FinishMount() { // 重新启用玩家控制器,但此时控制器变成“骑马控制”逻辑 playerController.SetActive(true); // 这里可以切换到一个“骑马状态”的组件 }}注意:上马动画不要用Root Motion,否则角色会乱跑。我们直接强制位移到锚点,然后播放一个“贴合”动画,视觉上看起来就像真的跨上去一样。## 三、摄像机跟随:别让镜头穿墙或穿马头骑马时的摄像机与走路时不同,因为马的身位更高、转弯半径更大。常见的做法是使用 “第三人称智能摄像机”,但需要调整跟随的偏移量和碰撞检测。### 1. 摄像机避障:SphereCast骑马时玩家和马是一个“长条形”碰撞体,摄像机如果直接放在背后,很容易撞到墙壁或树木。我们可以用球体投射(SphereCast)来检测遮挡,然后平滑调整摄像机位置。csharp// Unity C# 示例:骑马摄像机避障using UnityEngine;public class HorseCamera : MonoBehaviour{ public Transform target; // 马的头部或骑手头部 public float distance = 5f; public float height = 2f; public float smoothSpeed = 10f; private Vector3 desiredPos; private Vector3 currentVelocity; void LateUpdate() { // 理想位置:目标后方+高度 Vector3 behindDir = -target.forward; desiredPos = target.position + behindDir * distance + Vector3.up * height; // 用球体投射检测遮挡 RaycastHit hit; if (Physics.SphereCast(target.position, 0.3f, desiredPos - target.position, out hit, distance)) { // 如果被遮挡,将摄像机拉近到碰撞点附近 desiredPos = target.position + (desiredPos - target.position).normalized * (hit.distance - 0.3f); } // 平滑移动 transform.position = Vector3.SmoothDamp(transform.position, desiredPos, ref currentVelocity, smoothSpeed * Time.deltaTime); transform.LookAt(target.position + Vector3.up * 1.5f); }}这里用 SphereCast 而不是 LineCast,因为马身体宽,细线检测容易漏掉侧面的墙。### 2. 视角跟随马头方向骑马时,玩家通常希望视角跟随马头转弯,而不是跟随骑手。所以摄像机目标应该设为马的头部骨骼(或马头前方的一个空物体),这样转弯时镜头会有自然的甩动感。## 四、总结骑马系统看似简单,实则是一个“动画、物理、输入、摄像机”四者协同的微型系统工程。核心要点回顾:1. 动画分层:用Layer和Avatar Mask分离骑手上下半身动作,让骑手能自由攻击或做表情。2. 骨骼对齐:利用锚点+LateUpdate强制对齐骑手与马背,避免穿模。3. 交互状态机:上马前先“走到位”,再“吸附+播放过渡动画”,实现无缝衔接。4. 摄像机避障:用SphereCast处理遮挡,并让镜头跟随马头方向,增强沉浸感。最后,别忘了在骑马状态下修改玩家的碰撞体(比如变成马匹的碰撞体),否则你会被自己角色的胶囊体卡住。希望这篇文章能帮你少走弯路,快去试试做一匹听话的“小马驹”吧!


《第三人称——骑马系统以及交互动画》 是转载文章,点击查看原文。


相关推荐


Go Modules 包管理详解:go.mod、go.sum 与依赖管理
程序员爱钓鱼2026/7/26

Go 编程实战系列(五) 上一篇《第一个 Go 程序:Hello World》中,我们创建了第一个 Go 项目,并执行过这样一条命令: go mod init hello-go 执行完成后,项目目录中会出现一个 go.mod 文件。 很多初学者第一次看到它时可能会疑惑: go.mod 到底有什么用?Go 项目的第三方库从哪里下载?为什么有时还会出现 go.sum?go get 和 go mod tidy 又有什么区别? 这些问题都与 Go Modules 有关。 Go Modules 是现代


Alibaba买家账号运营指南:注册流程、账号养护及多账号管理实践
xiaobaihuoke2026/7/18

在跨境电商行业中,很多企业把重点放在卖家账号运营、产品推广以及广告投放上,但实际上,一个稳定、高质量的买家账号,同样是跨境运营体系中不可忽视的重要资源。 无论是进行海外市场调研、寻找供应商、分析行业趋势,还是获取产品报价,一个真实、活跃的Alibaba国际站买家号,都能够帮助企业更加深入了解市场。 然而,随着Alibaba平台风控机制不断完善,买家账号的运营已经不再是简单注册即可使用。账号注册后的行为习惯、活跃程度以及采购轨迹,都会影响账号后续的使用价值。 因此,买家号运营逐渐形成了一个完


再见Fable 5,OpenAI出手了!GPT-5.6真香~
AI袋鼠帝2026/7/10

大家好,我是袋鼠帝 我最近在疯狂使用Fable 5,好用是好用,就是太贵啦! 不过不是在Claude 官方使用的,因为我最新的一个号,在7月1号又tm被封了,服了都(已经记不清是第几个了) 天下苦A社久矣.. 所以,我最近都是在Cursor上用的Fable 5,虽然我下血本充了200$的订阅,但跑了两天Fable 5,总用量就已经超过48%了。。。 整的我都有点不敢用了,除非核心任务,其他时候我都只敢开启auto模式(自动选择模型) 就是这么憋屈。 然后今天凌晨,OpenAI终于出手了! G


从零构建ReAct智能体:让AI学会边想边做
树獭非懒2026/7/2

前言 大语言模型已经能写诗、编程、做数学题,但它有一个根本性的短板:无法与外部世界交互。你问它"今天深圳天气怎么样",它只能诚恳地告诉你"我的知识截止到某某日期"——不是它不想回答,是它根本没有"看天气"这个动作能力。 这就是智能体(Agent)要解决的核心问题:让 LLM 不仅能想,还能做。 业界现有的智能体框架(LangChain、LlamaIndex 等)已经将这套机制封装得非常完善,但它们的高度抽象也让很多人停留在"调包侠"阶段,对背后的运行机制一知半解。本文的目标,是带你从零构建一个


Swift 还让你 Excited 吗?-- 肘子的 Swift 周报 #141
东坡肘子2026/6/23

Swift 还让你 Excited 吗? 上周,Reddit 上一篇题为《Is anyone else excited by Swift progress as the language?》的帖子引发了不少讨论。WWDC 2026 上,Apple 明确表示,Swift 已被用于 WebKit 关键组件、QUIC 网络栈、字体渲染、驱动与固件。发帖者据此认为,Swift 正在向核心操作系统内核迈进,并将这一幕视为 2014 年"高级系统编程语言"承诺的兑现。评论区的讨论则很快从“是否兑现了承诺”,


别再让业务层裸奔 CarPropertyManager 了!谈谈汽车车载核心服务的架构封装
潜龙勿用之化骨龙2026/6/15

前言 Android Automotive 项目中,CarPropertyManager 几乎是访问一切车辆状态的入口。但在真实项目里,如果直接在 ViewModel 或业务层大量使用它,代码会变得难以维护、难以测试,也完全不符合 现代Android 架构 的分层思想。 本文将从零开始,梳理一套基于 Clean Architecture 的 CarPropertyManager 封装方案,涵盖: 为什么不能直接用 如何用抽象基类统一封装 callbackFlow 的正确姿势 Flow 与 su


「装闭」-AI驱动的开源装修闭坑系统
fthux2026/6/8

愿每个业主在装修路上心中有数,于是,「装闭」来了。 装修行业的水有点儿深 很多人装修完回头看,都发现自己花了不少冤枉钱。设计师画的效果图美轮美奂——复杂吊顶、满墙背景墙、开放格书架……装好以后才发现,这些东西费钱不说,日常打理还特别费劲。吊顶积灰、开放格藏污纳垢、花哨灯带一年到头开不了几次。 更别说合同和报价单里的猫腻。增项漏项、模糊工艺描述、虚报材料数量——这些套路装修公司玩得轻车熟路,但普通业主根本无从分辨。随便一个增项,几千块甚至上万块就多出来了。 于是就有了「装闭」(RenoPit)这


译 · Jake Wharton 访谈:Android 圈最熟悉的那个名字
bqliang2026/6/1

Jake Wharton 是我的偶像,也是很多 Android 开发者绕不开的名字。Retrofit、OkHttp、Dagger、Ktx... 这些项目或多或少都影响过我们写 Android 的方式。 前几天在网上看到他的这篇访谈,读完觉得很受用。里面既有他早年做 Android、做开源的经历,也有他对职业选择、会议、倦怠、家庭和工作方式的很多真实想法。这里把它翻译成中文,分享给同样喜欢 Android、Kotlin 和开源的朋友们。 ⚡️ 欢迎来到 Effective Interviews


从 textarea 到 AI 输入框:用 Tiptap 实现 / 命令、@ 引用和结构化请求
倾颜2026/5/11

本文对应项目版本:v0.0.12 在一个 AI 应用刚开始做聊天功能时,textarea 往往已经够用了。 用户输入一段自然语言,前端把它发给后端,后端拿到消息数组,模型开始生成回答。这个链路简单、直接,也足够支撑最早期的问答场景。 但当项目里慢慢出现 Skill(任务能力层)、Tool(可执行工具)、Resource(可读取上下文)、Prompt(可注入模型的提示模板)、MCP 能力(通过 MCP 接入的外部能力)之后,我开始遇到一个更具体的问题:用户输入不再只是一段自然语言。 它开始同时表


解决 4 大 AI 编码痛点:Matt Pocock 的 Skill 工作流深度拆解
小碗细面 VIP.5 如鱼得水2026/5/1

解决 4 大 AI 编码痛点:Matt Pocock 的 Skill 工作流深度拆解 当所有人都在用 AI 写更多代码的时候,TypeScript 之神 Matt Pocock 把自己的 .claude 目录直接推到 GitHub 上,告诉我们:先别急着 vibe coding,把工程基本功捡回来。 一、写在前面:一个让人拍大腿的开源项目 2026 年 3 月,TypeScript 社区的"老熟人"Matt Pocock(你大概率在他的 Total TypeScript 课程下面留过言)干了

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2026 聚合阅读