我试图让“球体”节点仅跟随手指在屏幕上的x轴方向运动,而不影响球体的y或z值。我不确定是否应该对物理物体施加力或使用SCNAction对其进行移动。球体将在占据屏幕宽度的多维数据集节点上反弹。到目前为止,我最大的问题是弄清楚在手势功能中应包含什么内容。这是我要复制的内容的一个示例,用户在屏幕上滑动手指,球镜像其位置。
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches {
let touchLocation = t.location(in: self.view)
let touchCoordinatesX = (touchLocation.x - self.scnView.frame.width / 2)
ballNode.position.x = Float(touchCoordinatesX/75)
}
}
上面的代码有些起作用,当我在屏幕上拖动手指时,y位置会跳出来,并且即使我的代码从不编辑球的y值,它也会迅速快速地上下移动。每次我在屏幕上拖动时,将球的y位置添加到场景的根节点时,它的y位置都会重置为其原始值。
根据您的回答,这就是我所使用的,并且正是我所需要的。
@objc func handlePan(recognizer: UIPanGestureRecognizer)
{
currentLocation = recognizer.location(in: self.view)
let touchCoordinatesX = (currentLocation.x - self.scnView.frame.width / 2)
if recognizer.state == .changed
{
ballNode.position.x = Float(touchCoordinatesX/75)
ballNode.position.y = ballNode.presentation.position.y
}
}
最佳答案
尝试handlePan并设置/保存dragMode状态变量。下面的代码是我用来选择面板和扫视屏幕的代码,因此其中包含一些额外的代码,但是我认为您可以根据需要进行修改。在您的情况下,我的“跨越屏幕”应该类似于您将球拖向指尖的需要。
如果将您的球对象在dragChanges()中设置为currentLocation.x,则它应在您的指尖上精确对齐,并且响应应迅速发生。根据您的图片,我的猜测是您希望稍稍延迟一下,以便更加真实。如果是这种情况,我建议您添加一个计时器并处理一小列已保存的X位置队列,以使其以较小的增量到达您的指尖。
希望能有所帮助。
//**************************************************************************
@objc func handlePan(recognizer: UIPanGestureRecognizer)
{
currentLocation = recognizer.location(in: gameScene)
let getLocation: CGPoint = recognizer.location(in: gameScene)
let panHitTestResults = gameScene.hitTest(getLocation, options: hitTestOptions)
if(data.gameState == .endWave || data.gameState == .endGame ||
data.gameState == .defenseAdd || data.gameState == .defenseUpgrade)
{
dragMode = .none
selectorActive = false
lastPanelSelected = ""
return
}
// State Begins
if recognizer.state == UIGestureRecognizerState.began
{
dragMode = .drag
beginLocation = recognizer.location(in: gameScene)
data.panX = currentLocation.x
data.lastMouseX = Float(beginLocation.x)
data.lastMouseY = Float(beginLocation.y)
dragBegins(vRecognizer: recognizer)
selectorActive = false
}
// State Changes
if(recognizer.state == UIGestureRecognizerState.changed)
{
dragChanges(vRecognizer: recognizer)
if(data.gameState == .run && dragMode == .drag)
{
// If we were selecting cursor and want to cancel, just touch with 2 fingers
if(recognizer.numberOfTouches == 2)
{
dragMode = .none
selectorActive = false
grid.cancelCursor()
return
}
for vHit in panHitTestResults
{
if(vHit.node.name?.prefix(5) == "Panel")
{
selectorActive = true
lastPanelSelected = vHit.node.name!
data.panelSelected = lastPanelSelected
let _ = grid.selectCursor()
return
}
}
}
}
if(recognizer.state == UIGestureRecognizerState.ended)
{
dragEnds(vRecognizer: recognizer)
dragMode = .none
if(selectorActive == true)
{
gameControl.selectPanel(vPanel: lastPanelSelected)
lastPanelSelected = ""
selectorActive = false
return
}
}
}
//**************************************************************************
func dragBegins(vRecognizer: UIPanGestureRecognizer)
{
if(data.gameState == .run)
{
if(vRecognizer.numberOfTouches == 2) { dragMode = .strafe }
}
}
//**************************************************************************
func dragChanges(vRecognizer: UIPanGestureRecognizer)
{
if(data.gameState == .run)
{
if(dragMode == .strafe && vRecognizer.numberOfTouches == 1)
{
dragMode = .none
return
}
switch(dragMode)
{
case .strafe:
gNodes.camera.strafe(vX: Float(currentLocation.x), vY: Float(currentLocation.y))
break
case .none:
break
default:
break
}
}
}
//**************************************************************************
func dragEnds(vRecognizer: UIPanGestureRecognizer)
{
if(data.gameState == .run)
{
switch(dragMode)
{
case .strafe:
break
default:
break
}
}
dragMode = .none
}
关于ios - SceneKit SCNNode跟随触摸运动,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53255523/