首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法在SK3DNode上显示雪碧

无法在SK3DNode上显示雪碧
EN

Stack Overflow用户
提问于 2020-05-03 05:13:00
回答 2查看 218关注 0票数 3

我在SpriteKit场景中显示一些基本的三维几何,使用SK3DNode实例来显示SceneKit场景的内容,如苹果公司的文章中所解释的那样。

我已经能够使用SceneKit节点转换和SK3DNode的位置/视口大小来定位节点和3D内容。

接下来,我想在我的SpriteKit场景中显示一些其他精灵,覆盖在3D内容之上,但我无法这样做: SK3DNode的内容总是绘制在顶部。

我已经尝试指定SK3DNode和SKSpriteNode的SK3DNode属性,但没有效果。

来自苹果在SK3DNode上的文档:

使用SK3DNode对象将3D SceneKit内容合并到一个基于SpriteKit的游戏中。当SpriteKit呈现节点时,首先动画并呈现SceneKit场景。然后将呈现的图像合成到SpriteKit场景中。使用scnScene属性指定要呈现的SceneKit场景。

(强调地雷)

对于z顺序,它有点模糊(它似乎只提到呈现发生的时间顺序)。

我已经组装了一个基于GitHub的最小演示项目;相关代码是:

1. SceneKit场景

代码语言:javascript
复制
import SceneKit
class SceneKitScene: SCNScene {

    override init() {
        super.init()

        let box = SCNBox(width: 10, height: 10, length: 10, chamferRadius: 0)
        let material = SCNMaterial()
        material.diffuse.contents = UIColor.green
        box.materials = [material]

        let boxNode = SCNNode(geometry: box)
        boxNode.transform = SCNMatrix4MakeRotation(.pi/2, 1, 1, 1)

        self.rootNode.addChildNode(boxNode)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

2. SpriteKit场景

代码语言:javascript
复制
import SpriteKit
class SpriteKitScene: SKScene {

    override init(size: CGSize) {
        super.init(size: size)

        // Scene Background
        self.backgroundColor = .red

        // 3D Node
        let objectNode = SK3DNode(viewportSize: size)
        objectNode.scnScene = SceneKitScene()
        addChild(objectNode)
        objectNode.position = CGPoint(x: size.width/2, y: size.height/2)

        let camera = SCNCamera()
        let cameraNode = SCNNode()
        cameraNode.camera = camera
        objectNode.pointOfView = cameraNode
        objectNode.pointOfView?.position = SCNVector3(x: 0, y: 0, z: 60)
        objectNode.zPosition = -100

        // 2D Sprite
        let sprite = SKSpriteNode(color: .yellow, size: CGSize(width: 250, height: 60))
        sprite.position = objectNode.position
        sprite.zPosition = +100
        addChild(sprite)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

...And 呈现的结果是:

(我想要黄色矩形上方的绿色框)

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-05-15 16:34:18

我和苹果公司发生了一起技术支持事件,他们刚刚联系到我。解决办法其实很简单。

如果您希望2D精灵在SK3DNodes之上呈现,则需要停止SK3DNodes的内容写入深度缓冲区。

为此,只需将writesToDepthBuffer设置为SCNMaterial上的false即可。

代码语言:javascript
复制
...

let material = SCNMaterial()
material.diffuse.contents = UIColor.green
material.writesToDepthBuffer = false

...

轰隆隆。很管用。

票数 4
EN

Stack Overflow用户

发布于 2020-05-13 01:52:38

请注意,这只是我偶然发现的。,我不知道它为什么会起作用,如果没有进一步的理解,我可能不会相信它,但也许它会帮助我找到一个解释或一个真正的解决方案。

似乎有一个SKShapeNode (带一个填充)与一个SK3DNode (或者作为一个兄弟,一个兄弟树的一部分,或者一个子)按照正确的顺序绘制它。SKShapeNode似乎也不需要与SK3DNode交叉。

填充是很重要的,因为有一个透明的填充使得这不起作用。中风似乎没有任何效果。

一个非常小尺寸和几乎为零阿尔法填充的SKShapeNode也能工作。

这是我的操场:

代码语言:javascript
复制
import PlaygroundSupport
import SceneKit
import SpriteKit

let viewSize = CGSize(width: 300, height: 150)
let viewportSize: CGFloat = viewSize.height * 0.75

func skview(color: UIColor, index: Int) -> SKView {
    let scene = SKScene(size: viewSize)
    scene.backgroundColor = color

    let view = SKView(
        frame: CGRect(
            origin: CGPoint(x: 0, y: CGFloat(index) * viewSize.height),
            size: viewSize
        )
    )
    view.presentScene(scene)
    view.showsDrawCount = true

    // Draw the box of the 3d node view port
    let viewport = SKSpriteNode(color: .orange, size: CGSize(width: viewportSize, height: viewportSize))
    viewport.position = CGPoint(x: viewSize.width / 2, y: viewSize.height / 2)
    scene.addChild(viewport)

    return view
}

func cube() -> SK3DNode {
    let mat = SCNMaterial()
    mat.diffuse.contents = UIColor.green

    let box = SCNBox(width: viewportSize, height: viewportSize, length: viewportSize, chamferRadius: 0)
    box.firstMaterial = mat

    let boxNode3d = SCNNode(geometry: box)
    boxNode3d.runAction(.repeatForever(.rotateBy(x: 10, y: 10, z: 10, duration: 10)))

    let scene = SCNScene()
    scene.rootNode.addChildNode(boxNode3d)

    let boxNode2d = SK3DNode(viewportSize: CGSize(width: viewportSize, height: viewportSize))
    boxNode2d.position = CGPoint(x: viewSize.width / 2, y: viewSize.height / 2)
    boxNode2d.scnScene = scene

    return boxNode2d
}

func shape() -> SKShapeNode {
    let shape = SKShapeNode(rectOf: CGSize(width: viewSize.height / 4, height: viewSize.height / 4))
    shape.strokeColor = .clear
    shape.fillColor = .purple
    return shape
}

func rect(_ color: UIColor) -> SKSpriteNode {
    let sp = SKSpriteNode(texture: nil, color: color, size: CGSize(width: 200, height: viewSize.height / 4))
    sp.position = CGPoint(x: viewSize.width / 2, y: viewSize.height / 2)
    return sp
}

// The original issue, untouched.
func v1() -> SKView {
    let v = skview(color: .red, index: 0)

    v.scene?.addChild(cube())
    v.scene?.addChild(rect(.yellow))

    return v
}

// Shape added as sibling after the 3d node. Notice that it doesn't overlap the SK3DNode.
func v2() -> SKView {
    let v = skview(color: .blue, index: 1)

    v.scene?.addChild(cube())
    v.scene?.addChild(shape())
    v.scene?.addChild(rect(.yellow))

    return v
}

// Shape added to the 3d node.
func v3() -> SKView {
    let v = skview(color: .magenta, index: 2)

    let box = cube()
    box.addChild(shape())

    v.scene?.addChild(box)
    v.scene?.addChild(rect(.yellow))

    return v
}

// 3d node added after, but zPos set to -1.
func v4() -> SKView {
    let v = skview(color: .cyan, index: 3)

    v.scene?.addChild(shape())
    v.scene?.addChild(rect(.yellow))

    let box = cube()
    box.zPosition = -1
    v.scene?.addChild(box)

    return v
}

// Shape added after the 3d node, but not as a sibling.
func v5() -> SKView {
    let v = skview(color: .green, index: 4)

    let parent = SKNode()
    parent.addChild(cube())
    parent.addChild(rect(.yellow))

    v.scene?.addChild(parent)
    v.scene?.addChild(shape())

    return v
}

let container = UIView(frame: CGRect(origin: .zero, size: CGSize(width: viewSize.width, height: viewSize.height * 5)))
container.addSubview(v1())
container.addSubview(v2())
container.addSubview(v3())
container.addSubview(v4())
container.addSubview(v5())

PlaygroundPage.current.liveView = container

TL;博士

在您的代码中,尝试:

代码语言:javascript
复制
...

let shape = SKShapeNode(rectOf: CGSize(width: 0.01, height: 0.01))
shape.strokeColor = .clear
shape.fillColor = UIColor.black.withAlphaComponent(0.01)

// 3D Node
let objectNode = SK3DNode(viewportSize: size)
objectNode.addChild(shape)

...
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61569914

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档