在游戏引擎布局中使用shared_ptr

Use shared_ptr in Game Engine layout?

本文关键字:shared ptr 游戏 引擎 布局      更新时间:2023-10-16

我在C 上写了一个小游戏引擎,它可以正常工作,但不是最好的表演。我也学到了很多东西,我想现在重做。但是上次我大量使用共享的_ptr来用于GUI纹理和模型包装器(即3D位置和OpenGL VAO)等类。我已经听说不应该真正使用shared_ptr,但是我真的不知道该怎么做。这是类似伪代码的布局:

此代码不完整或有效,但我想分享我的布局

的想法
// d3 stands for 3d
class D3Model {
    VAO vao;
    bool useBloom;
    unsigned int texture;
    // ... and so on
    static std::vector<std::shared_ptr<D3Model>> models; // current idea, approach 1
    static std::vector<D3Model> models1; // different approach (2)
    D3Model() {
        models.push_back(shared_from_this()); // app.1
        models1.push_back(*this);
    }
}

// main file
int main() {
    std::shared_ptr<D3Model> model = std::make_shared<D3Model>();
    model->setTexture(0); // ignore the non sense content
    D3Model model1;
    model1.setTexture(0); // would not get updated in the vector
    while(true) {
        model->increaseRotation(1);
        model1.increaseRotation(1);
        Renderer::render();
    }
}
// different file
class Renderer {
    static void render() {
        for(const auto& all : D3Model::models) {
            // render model
        }
        for(const auto& all : D3Model::models1) {
            // render model1, would not have increased rotation
        }
    }
}

要进行更多澄清,请想象引擎的以下使用:在开始屏幕上播放播放后,引擎从文件中加载了一些3D型号并存储它们。其中一个旋转每个框架,每个框架都会渲染。由于游戏玩法的变化(玩家加入...),也许必须加载其他一些型号。然后,当用户返回主菜单时,它们都将被删除。我在方法2的问题是,每次增加模型的旋转时,我都必须更新矢量,而该方法会自动使用方法1进行处理。但是,我听到了共享_ptr对性能不利。

对于这种情况,共享_ptr是最好的解决方案,还是我应该只使用普通对象?但是我的问题是,我将如何将更改应用于对象(例如setTexture),而无需更新矢量内容。原始的指针也非常好。这样的事情怎么办?谢谢,虚幻

好的,您可以像我这样创建自己的repcouner类:

/// RefCounter.hpp
#pragma once
class RefCounter {
public:
    RefCounter();
    RefCounter(const RefCounter&);
    RefCounter& operator=(const RefCounter&);
    void grab();
    usize reference() const;
    bool release();
protected:
    virtual void finalize();
    virtual ~RefCounter();
private:
    usize _reference;
};

template<typename T>
struct ref {
    inline ref() : class_ptr (nullptr) {}
    inline ref(T* obj) : class_ptr (obj) { if(class_ptr) class_ptr->grab(); }
    inline ref(const ref& other) : class_ptr (other.class_ptr) { if(class_ptr) class_ptr->grab(); }
    inline ref& operator=(T* obj) {
        if(obj)
            obj->grab();
        if(class_ptr)
            class_ptr->release();
        class_ptr = obj;
        return *this;
    }
    inline ref& operator=(const ref& other){
        T* obj = other.class_ptr;
        if(obj)
            obj->grab();
        if(class_ptr)
            class_ptr->release();
        class_ptr = obj;
        return *this;
    }
    T* get() const {
        return class_ptr;
    }
    operator T*() const {
        return class_ptr;
    }
    T* operator->() const {
        return class_ptr;
    }
    inline ~ref() {
        if(class_ptr)
            class_ptr->release();
    }
private:
    T* class_ptr;
};
/// RefCounter.cpp

RefCounter::RefCounter() : _reference(0){
}
RefCounter::RefCounter(const RefCounter&) : _reference(0) {
}
RefCounter& RefCounter::operator=(const RefCounter&) {
    return *this;
}
void RefCounter::grab() {
    _reference++;
}
usize RefCounter::reference() const {
    return _reference;
}
bool RefCounter::release() {
    if(_reference > 1) {
        _reference--;
        return false;
    } else {
        _reference = 0;
        finalize();
        return true;
    }
}
void RefCounter::finalize() {
    delete this;
}
RefCounter::~RefCounter() {
}