ios – 检查SCNNode SCNAction是否完成

我已经创建了一个玩家可以移动的SceneKit 3D迷宫世界.像跳跃这样的一些动作涉及在几秒钟的时间段内改变观察方向时上下移动相机.在此期间,我想忽略用户的轻击和滑动,这通常会导致其他类型的动作,如转弯和前进.

我可以创建一个匹配跳转持续时间的计时器并设置Bool,但我希望能够以更简单的方式检查摄像机的SCNNode.

有没有一种简单的方法来查看相机的SCNNode是否不再运行SCNAction跳转,所以我可以在其他点按和滑动操作之前添加此逻辑?

或者也许有一个SCNAction可以设置我可以在跳转序列的开始和结束时放置的Bool?

这是我的跳转代码:

let jumpUp: SCNAction = SCNAction.move(to: SCNVector3Make(Float(Int(-yPos)),Float(Int(xPos)),jumpHeight),duration: jumpTime)
        let jumpAppex: SCNAction = SCNAction.wait(duration: jumpWaitTime)
        let fallDown: SCNAction = SCNAction.move(to: SCNVector3Make(Float(Int(-yPos)),cameraHeight),duration: jumpTime)

        var lookDown: SCNAction = SCNAction.rotateTo(x: 0,y: 0,z: CGFloat(π),duration: jumpTurnTime)
        let noLook: SCNAction = SCNAction.wait(duration: jumpTime*2.0)
        var lookBack: SCNAction = SCNAction.rotateTo(x: 0,z: 0,duration: jumpTurnTime)

        switch playerDirection.direction
        {
            case .south:
                lookDown = SCNAction.rotateTo(x: 0,z: CGFloat(southZ),duration: jumpTurnTime)
                lookBack = SCNAction.rotateTo(x: CGFloat(π/2),duration: jumpTurnTime)
            case .north:
                lookDown = SCNAction.rotateTo(x: 0,z: CGFloat(northZ),duration: jumpTurnTime)
            case .east:
                lookDown = SCNAction.rotateTo(x: 0,z: CGFloat(eastZ),duration: jumpTurnTime)
            case .west:
                lookDown = SCNAction.rotateTo(x: 0,z: CGFloat(westZ),duration: jumpTurnTime)
        }

        let sequenceJump = SCNAction.sequence([jumpUp,jumpAppex,fallDown])
        let sequenceLook = SCNAction.sequence([lookDown,noLook,lookBack])

        mazeScene.mazeCamera.runAction(sequenceJump)
        mazeScene.mazeCamera.runAction(sequenceLook)

谢谢

格雷格

解决方法

我认为,行动是非常奇怪的事情.

这个想法深受启发(基本上是1:1的映射和’盗窃’)来自cocos2D,在那里它们被用来避免与游戏循环,状态和时间(某种程度)直接交互.动作提供了一种模块化和抽象,用于处理时间,创建和调用活动,以及对结论的非常原始的处理.

在这里阅读时,你可以看到SpriteKit和SceneKit的动作与原始想法有多相似:http://python.cocos2d.org/doc/programming_guide/actions.html

由于他们创造的不同和不断演变的性质,有人忘记让他们意识到自己的状态,尽管他们影响节点状态的某些方面.如果Action对象具有“运行”状态,那将近乎完美.但就我所知,他们没有.

相反,您可以检查Node是否具有给定的Action,如果有,则推断Action正在运行.

尽管大多数行动在一段时间内都在做某些事情,但你也无法询问他们在整个持续时间内完成了多少事情,也没有询问他们刚刚解雇或将接下来发送的价值.但是有一些动作可以做到这一点,特别是为了应对所有动作都缺失的事实意味着如果你想要这个,你需要使用一个特殊的动作提供这个.

对于应该是天生的设施而言,这种递归和回归自我是动作中最烦人的部分,而不是从熟悉时间轴和关键帧的人的角度进行思考.

整体而言,总结:您无法查询某个操作的状态,也无法查询其进度或它刚刚执行或将要使用的值.这绝对是荒谬的.

我不知道在各种行动的演变中如何忽视这一点……他们是时间管理和模块化活动的创造者.将状态和进度报告纳入其中似乎是合乎逻辑的……好吧,我不知道……只是奇怪的是他们没有.

那么,回答你的问题:

>您可以使用完成处理程序,它可以在Action完成时调用某些代码,设置值或调用其他函数或清理内容,或者您​​想要的任何内容.
>序列动作,在SCNAction.sequence中…这是一种顺序运行Action的方法,并且在内部使用一些在需要时运行代码块的Action,可以在需要时调用设置所需的内容,行动的顺序.如果行动目前对时间和财产的价值具有透明度,那么所有这些都可以避免……但……
>您还可以使用少数特殊操作,这些操作通过对其进行的更改来了解他们正在编辑的值.我只熟悉SKEaseKit中的浮点设置能力,但你可能在SceneKit和SpriteKit中做到这一点(如果你是一个比我好得多的编码器). SKEaseKit隐藏了一些非常有用的值更改操作.

我使用它,例如,像这样,其中这个混乱在持续时间(时间)内将值0更改为1,在这种情况下是线性的,并且每个帧(希望)更新此growAction所在的节点的.xScale.跑:

let growAction = SKEase.createFloatTween(
                start: 0,ender: 1,timer: time,easer: SKEase.getEaseFunction(.curveTypeLinear,easeType: .easeTypeOut),setterBlock: {(node,i) in
            node.xScale = i}
            )

相关文章

当我们远离最新的 iOS 16 更新版本时,我们听到了困扰 Apple...
欧版/美版 特别说一下,美版选错了 可能会永久丧失4G,不过只...
一般在接外包的时候, 通常第三方需要安装你的app进行测...
前言为了让更多的人永远记住12月13日,各大厂都在这一天将应...