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

Swift中实现AR场景下车身随车轮联动移动与旋转的方法

Hey there! Let's get those wheels spinning in sync with your AR car's movement—here's a straightforward approach based on your existing code:

Step 1: Save References to Your Wheel Nodes

First, you need to grab and store references to the wheel nodes in your car model so you can manipulate them later. Use the node names from your 3D model (adjust these names to match your actual model's wheel nodes):

// Add these properties to your class
var carNode: SCNNode?
var frontLeftWheel: SCNNode?
var frontRightWheel: SCNNode?
var rearLeftWheel: SCNNode?
var rearRightWheel: SCNNode?

// Update your touchesBegan method to save these references
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    if let touch = touches.first {
        let touchLocation = touch.location(in: sceneView)
        let results = sceneView.hitTest(touchLocation, types: .existingPlaneUsingExtent)
        
        if let hitResult = results.first {
            let boxScene = SCNScene(named: "art.scnassets/porsche.scn")!
            carNode = boxScene.rootNode.childNode(withName: "car", recursively: true)
            
            guard let carNode = carNode else { return }
            
            // Save wheel nodes (use YOUR model's actual wheel node names)
            frontLeftWheel = carNode.childNode(withName: "frontLeftWheel", recursively: true)
            frontRightWheel = carNode.childNode(withName: "frontRightWheel", recursively: true)
            rearLeftWheel = carNode.childNode(withName: "rearLeftWheel", recursively: true)
            rearRightWheel = carNode.childNode(withName: "rearRightWheel", recursively: true)
            
            // Position the car as before
            carNode.position = SCNVector3(
                x: hitResult.worldTransform.columns.3.x,
                y: hitResult.worldTransform.columns.3.y + 0.15,
                z: hitResult.worldTransform.columns.3.z
            )
            
            sceneView.scene.rootNode.addChildNode(carNode)
        }
    }
}

Step 2: Track Car Position & Calculate Movement Distance

To sync wheel rotation with movement, you need to measure how far the car moves each frame. Add a property to track the car's previous position, then calculate the distance traveled when moving the car:

// Add this property to your class
var lastCarPosition: SCNVector3?

// Example method for moving the car forward (attach this to your accelerate button)
func accelerateCar(speed: Float) {
    guard let carNode = carNode else { return }
    
    // Define forward direction (adjust based on your model's orientation—most models use -z for forward)
    let forwardDir = SCNVector3(0, 0, -1)
    let movement = forwardDir * speed * Float(1/60) // Adjust for 60fps refresh
    
    // Update car position
    let newPosition = carNode.position + movement
    carNode.position = newPosition
    
    // Calculate distance traveled and update wheels
    if let lastPos = lastCarPosition {
        let distance = calculateDistance(from: lastPos, to: newPosition)
        rotateWheels(distance: distance, isForward: true)
    }
    
    // Save current position for next frame
    lastCarPosition = newPosition
}

// Helper function to calculate 3D distance between two points
func calculateDistance(from a: SCNVector3, to b: SCNVector3) -> Float {
    let dx = a.x - b.x
    let dy = a.y - b.y
    let dz = a.z - b.z
    return sqrt(dx*dx + dy*dy + dz*dz)
}

Step 3: Rotate Wheels Based on Movement

Wheels rotate based on the distance traveled—each full rotation equals the wheel's circumference (2πr). Adjust the wheel radius to match your model's actual size:

func rotateWheels(distance: Float, isForward: Bool) {
    // Replace this with your wheel's actual radius (measure from your 3D model!)
    let wheelRadius: Float = 0.3
    
    // Calculate rotation angle: distance / radius (since circumference = 2πr, angle = distance/r)
    var rotationAngle = distance / wheelRadius
    if !isForward { rotationAngle *= -1 } // Reverse rotation for reverse
    
    // Update wheel rotation (adjust the axis if needed—most wheels rotate around the x-axis)
    frontLeftWheel?.eulerAngles.x += rotationAngle
    frontRightWheel?.eulerAngles.x += rotationAngle
    rearLeftWheel?.eulerAngles.x += rotationAngle
    rearRightWheel?.eulerAngles.x += rotationAngle
}

Step 4: Add Steering Logic (Bonus!)

For your steering buttons, you can rotate the front wheels around the y-axis (adjust direction based on your model):

func steerLeft(angle: Float) {
    frontLeftWheel?.eulerAngles.y += angle
    frontRightWheel?.eulerAngles.y += angle
}

func steerRight(angle: Float) {
    frontLeftWheel?.eulerAngles.y -= angle
    frontRightWheel?.eulerAngles.y -= angle
}

Key Tips to Get It Right

  • Double-check node names: Your 3D model's wheel nodes might have different names (e.g., "Wheel_Front_L")—use your printed boxNode.childNodes output to find the correct names.
  • Adjust wheel radius: If wheels spin too fast/slow, tweak the wheelRadius value to match your model's actual scale.
  • Fix rotation direction: If wheels spin backward when moving forward, swap the += to -= in the rotation code.
  • Handle reverse movement: Call rotateWheels(distance: ..., isForward: false) in your reverse button action.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 10:01:35