rust - 遇到正确的设计模式

标签 rust

我正在尝试编写一个简单的游戏引擎,但是由于严格的借用规则,我在此处无法使用的常规模式无法正常工作。

有一个World结构,它拥有Object特征对象的集合。我们可以将它们视为游戏引擎中移动的物理对象。 World负责在每个游戏滴答声中分别调用updatedraw
World结构还拥有Event特征对象的集合。这些事件中的每一个都封装了一段任意的代码,这些代码在游戏滴答声期间会修改objects

理想情况下,Event特性对象具有单个方法do_event,该方法不接受World在每个游戏滴答期间都可以调用的参数。问题是特定的Event需要对其修改的对象具有可变的引用,但是这些对象归World拥有。当它为每个事件调用World时,我们可以让do_event将可变引用传递给必要的对象,但是它如何知道将哪些对象传递给每个事件对象呢?

如果这是C++或Python,则在构造特定的Event时,我会将事件的目标传递给构造函数,在该构造函数中保存该事件,然后在do_event期间使用它。显然,这在Rust中不起作用,因为目标都由World拥有,因此我们无法在其他地方存储可变引用。

我可以添加一些ID系统和一个查找表,以便World知道将哪些对象传递给Event,但这很麻烦且代价高昂。我怀疑我解决此类问题的全部方式都需要改变,但是,我很沮丧。

我的代码的草图:

trait Object {
    fn update(&mut self);
    fn draw(&self);
}

trait Event {
    fn do_event(&mut self);
}

struct World {
    objects: Vec<Box<dyn Object + 'a>>,
    events: Vec<Box<dyn Event + 'a>>,
}

impl World {
    fn update(&mut self) {
        for obj in self.objects.iter_mut() {
            obj.update();
        }
        for evt in self.events.iter_mut() {
            evt.do_event();
        }
    }
    fn draw(&mut self) { /*...*/ }
}

struct SomeEvent<'a, T: Object> {
    target: &'a mut T,
}

impl<'a, T: Object> Event for SomeEvent<'a, T> {
    fn update(&self) {
        self.target.do_shrink(); // need mutable reference here
    }
}

我知道RefCell允许多个对象获取可变引用。也许那是我应该走的方向。但是,基于what I learned from the Rust book,我感觉到RefCell通过引入不安全的代码和循环引用破坏了Rust的一些主要思想。我想我只是想知道是否还有其他一些明显的设计模式更符合惯用的做事方式。

最佳答案

在阅读了问题注释并观看了kyren's RustConf 2018 talk(感谢trentcl)之后,我意识到面向我的游戏引擎的面向对象方法从根本上与Rust不兼容(或者至少相当困难)。

在一天左右的工作之后,我强烈建议您观看发布的视频,然后使用specs库(user2722968提到的ECS系统的实现)。

希望这对以后的人有所帮助。

关于rust - 遇到正确的设计模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59617276/

相关文章:

rust - 错误 : the type of this value must be known in this context

string - 如何将String评估为表达式以在Rust中对String进行算术运算,以便在用户在控制台上键入3 +1时得到4

macros - 有没有办法在 Rust 的公共(public)宏中使用私有(private)函数?

rust - Cloudflare Workers 中的内存不足 WebAssembly 实例化

generics - 如何调用像 std::num::Float::epsilon() 这样的静态特征方法?

indexing - 对字符串和 `RangeFull`使用 `Borrow`语法

rust - Substrate 中来自比特币的 OP_RETURN <data> 相当于什么?

rust - 如何接受 Option<String>、处理它并返回 Option<String>?

rust - 您将如何流式传输流程的输出?

rust - Rust 项目的推荐目录结构是什么?