Swift SpriteKit 使用结构而不是类来渲染 Sprite

标签 swift struct skspritenode

我最近一直在更新我的游戏以使用更多值类型。在某些情况下,我对弱引用和无主引用仍然不是 100% 有信心,所以我采用了结构方式来避免强引用循环。根据苹果最新的主题演讲,看来值类型在大多数情况下都是可行的。

我从未见过在 spriteKit 游戏中使用结构来渲染 Sprite 的示例,所以我想知道它的缺点是什么。 我知道它们是复制的而不是引用的,但对于我的使用来说,它似乎有效。

那么基本上,在执行此操作时我需要注意什么

struct Flag {
   let post: SKSpriteNode
   let flag: SKSpriteNode

  init(postImage: String, flagImage: String) {
     post = SKSpriteNode(imageNamed: postImage)
     // other set ups for post sprite

     flag = SKSpriteNode(imageNamed: flagImage)
     // other set ups for flag sprite
     post.addChild(flag)
   }

   func animate() {
       // code to animate flag
   }
}

与我的 SKScenes 中相比,我只是照常添加它们

 let flag = Flag(postImage: "FlagPostImage", flagImage: "FlagImage")
 flag.post.position = ...
 addChild(flag.post)
 flag.animate()

现在,即使我在同一场景中创建多个标志,这种方式似乎也没有问题。 我只是很好奇,因为我从来没有真正见过这样的例子,所以我想知道我是否遗漏了一些东西,比如性能缺陷等。

感谢您的帮助。

最佳答案

我个人避免创建包含结构。由于 Structs 复制,在您的应用中传递的每个副本都会增加 Classes 的引用计数。这使得管理它们变得更困难而不是更容易。

了解 UIKit 如何使用 Structs 也很有用。 UIView 是一个对象,但具有许多定义属性,即 Structs。例如它是框架

将下面的代码放入 Playground 中以查看此行为的一些影响。 协议(protocol)只是为了从 Playground 获得一些有意义的反馈。

protocol IDLookable : CustomPlaygroundQuickLookable {

    var id : Int { get set }

}

extension IDLookable {

    func customPlaygroundQuickLook() -> PlaygroundQuickLook {
        return PlaygroundQuickLook.AttributedString(NSAttributedString(string: "\(self.dynamicType) with id : \(self.id)"))
    }
}


class MyClass : IDLookable {

    var id : Int = 0

    init(id : Int) {
        self.id = id
    }
}

struct MyContainerStruct : IDLookable {

    var id : Int = 0
    var object : MyClass

    init(id : Int, object:MyClass) {
        self.id = id
        self.object = object
    }
}

class Scope {

    // ref count = 1
    var object = MyClass(id: 11)
    var structContainer : MyContainerStruct

    init() {
        // ref count = 2
        structContainer = MyContainerStruct(id: 222, object: object)
        messWithAClassInAStruct()
    }

    func messWithAClassInAStruct() {

        // ref count = 3
        var structContainerTwo = structContainer
        structContainerTwo.id = 333
        structContainerTwo.object // 11

        // altering the object in one struct will obvously update all references
        structContainerTwo.object.id = 1
        structContainer.object // 1
        structContainerTwo.object // 1

    }
}

let test = Scope()

一种确实可以轻松使用值类型中的引用类型的模式是将它们存储为弱可选 >值类型。这意味着某些东西需要有强引用,但很可能某些Class将负责创建Structs这是一个好地方保持强有力的引用

struct MyContainerStruct : IDLookable {

    var id : Int = 0
    weak var object : MyClass?

    init(id : Int, object:MyClass) {
        self.id = id
        self.object = object
    }
}

class Scope {

    // ref count = 1
    var object = MyClass(id: 11)
    var structContainer : MyContainerStruct

    init() {
        // ref count = 1
        structContainer = MyContainerStruct(id: 222, object: object)
        messWithAClassInAStruct()
    }

    func messWithAClassInAStruct() {
        // ref count = 1
        var structContainerTwo = structContainer
        structContainerTwo.id = 333
        structContainerTwo.object // 11
    }
}

let test = Scope()

关于Swift SpriteKit 使用结构而不是类来渲染 Sprite ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35774088/

相关文章:

c++ - 使用结构名称作为函数

swift - 在节点的右边缘而不是中心旋转 SKSpriteNode

swift - 在不同位置生成多个节点

ios - 为 SKSpriteNode 选择随机图像

swift - 在swift中将字符串转换并格式化为字符数组

c++ - 在结构指针中修改 C 字符串

ios - 为什么我的 html 没有加载到我的 WKWebView

c - 在不引用外部结构的情况下在嵌套结构中声明内部结构变量

ios - 从扬声器获取音频样本

json - 使用 SwiftyJSON 解析 Alamofire JSON 结果