Unity中如何实现棋盘游戏棋子的逐格跳跃动画?
实现《Inscryption》风格的3D棋子逐格跳跃移动效果
核心思路是把棋子的整体移动路径拆分为单格移动段,每一段都实现「水平位移+弧形跳跃」的组合,而非直接从起点瞬移到终点。以下是具体实现方案:
步骤1:准备路径点列表
先确定棋子当前位置到目标位置之间的所有格子世界坐标,按移动顺序存入List<Vector3>。如果是规则网格棋盘,可借助Unity的Grid组件快速获取相邻格子坐标,或手动计算网格位置(比如每格间距为1时,相邻格子坐标差为(1,0,0)或(0,0,1))。
步骤2:用协程实现逐格跳跃移动
通过协程逐帧控制棋子位置,结合动画曲线或正弦函数实现跳跃弧度,避免和动画组件的位置控制冲突。
代码示例
using UnityEngine; using System.Collections.Generic; using System.Collections; public class PieceMovement : MonoBehaviour { public float moveTimePerTile = 0.3f; // 每格移动耗时(秒) public float jumpHeight = 0.6f; // 跳跃最大高度 public AnimationCurve jumpCurve; // 可在Inspector自定义跳跃曲线(可选,默认用正弦曲线) // 启动移动:传入预计算好的路径点列表 public void StartMove(List<Vector3> path) { StartCoroutine(MoveAlongPath(path)); } private IEnumerator MoveAlongPath(List<Vector3> path) { foreach (Vector3 targetTilePos in path) { Vector3 startPos = transform.position; // 确保目标格子和起点在同一水平面上(Y轴对齐) targetTilePos.y = startPos.y; float elapsed = 0f; while (elapsed < moveTimePerTile) { elapsed += Time.deltaTime; float progress = elapsed / moveTimePerTile; // 计算水平方向的插值位置 Vector3 horizontalPos = Vector3.Lerp(startPos, targetTilePos, progress); // 计算跳跃高度:用动画曲线或正弦函数 float jumpOffset = jumpCurve != null ? jumpCurve.Evaluate(progress) * jumpHeight : Mathf.Sin(progress * Mathf.PI) * jumpHeight; // 更新棋子位置 transform.position = new Vector3( horizontalPos.x, startPos.y + jumpOffset, horizontalPos.z ); yield return null; } // 强制对齐到目标格子,避免插值误差 transform.position = targetTilePos; } } }
关键细节说明
- 避免动画冲突:如果之前用动画组件导致位置被覆盖,要么关闭动画中对
transform.position的控制,要么直接用上述纯代码控制位移(更适合逐格跳跃的精确路径需求)。 - 路径生成逻辑:比如从格子
(0,0)移动到(2,0),路径点应该是[(0,0,y), (1,0,y), (2,0,y)],确保每一格都有独立的跳跃动作。 - 优化体验:移动过程中可以禁用棋子的交互组件(如
Button、Collider),防止重复触发移动指令。
内容的提问来源于stack exchange,提问作者Railson OL
相关产品推荐
相关产品推荐

