You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何关联SKSpriteNode位置与UIBezierPath的currentPoint并实现路径续走?

实现方案

要满足你的需求,核心是保存火车的运动状态和停止位置,并在返回场景时根据状态精准恢复。以下是具体实现步骤和代码调整:

1. 修正现有代码的逻辑错误

你的stopFollowTrainPath()里的guard条件写反了,应该确保myTrain存在时才执行移除动作和保存位置:

func stopFollowTrainPath() {
    guard let train = myTrain else { return }
    
    train.removeAction(forKey: runTrainKey)
    savedTrainPosition = train.position // 直接保存节点当前位置,无需冗余判断
    isTrainMoving = false // 标记为停止状态
}

2. 添加必要的状态变量

在GameViewController或对应的SKScene中添加三个状态变量,用于记录火车的关键状态:

// 标记火车是否处于移动状态
var isTrainMoving: Bool = false
// 保存火车停止时的位置
var savedTrainPosition: CGPoint = .zero
// 保存动作已执行的时间,用于恢复时精准回到断点
var savedElapsedTime: TimeInterval = 0

3. 优化启动动作的逻辑

在startFollowTrainPath()中添加状态标记,避免重复启动动作:

func startFollowTrainPath() {
    guard let train = myTrain else { return }
    
    // 如果已经在移动,先移除旧动作
    if train.action(forKey: runTrainKey) != nil {
        train.removeAction(forKey: runTrainKey)
    }
    
    let followAction = SKAction.follow(
        trainPath.cgPath,
        asOffset: false,
        orientToPath: true,
        speed: theSpeed
    )
    let repeatAction = SKAction.repeatForever(followAction)
    train.run(repeatAction, withKey: runTrainKey)
    isTrainMoving = true // 标记为移动状态
}

4. 完善停止时的状态记录

更新stopFollowTrainPath(),保存动作已执行的时间,确保恢复时能从断点继续:

func stopFollowTrainPath() {
    guard let train = myTrain else { return }
    
    if let runningAction = train.action(forKey: runTrainKey) {
        savedElapsedTime = runningAction.elapsedTime
        train.removeAction(forKey: runTrainKey)
    }
    savedTrainPosition = train.position
    isTrainMoving = false
}

5. 返回场景时的恢复逻辑

在场景的didMove(to view:)方法(或GameViewController中切换回场景的回调)中添加恢复逻辑:

func restoreTrainState() {
    guard let train = myTrain else { return }
    
    // 先恢复火车位置
    train.position = savedTrainPosition
    
    // 如果之前处于移动状态,从断点继续沿路径循环
    if isTrainMoving {
        let pathLength = trainPath.cgPath.length()
        let totalDuration = pathLength / theSpeed
        
        let followAction = SKAction.follow(
            trainPath.cgPath,
            asOffset: false,
            orientToPath: true,
            speed: theSpeed
        )
        let repeatAction = SKAction.repeatForever(followAction)
        
        // 设置时间偏移,让动作从停止的位置继续执行
        repeatAction.timeOffset = savedElapsedTime.truncatingRemainder(dividingBy: totalDuration)
        
        train.run(repeatAction, withKey: runTrainKey)
        isTrainMoving = true
    }
}

6. 调用时机

  • 切换到其他场景前:调用stopFollowTrainPath()记录状态
  • 回到当前场景后:调用restoreTrainState()恢复状态

这样就能完全满足需求:

  • 之前在移动的火车,从停止位置继续沿路径循环移动
  • 之前未移动的火车,保持停止时的位置不动

内容的提问来源于stack exchange,提问作者user22530416

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 18:25:21