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

如何在GameObject类的Collider成员中存储Transform引用并访问修改?

问题分析与解决方案

你碰到的核心问题是:当把GameObject对象存入vector时,vector扩容会触发对象的拷贝/移动,导致Collider中存储的Transform指针指向已销毁的旧对象,自然无法修改当前GameObject的Transform。

原因拆解

你的代码里,GameObject的构造函数初始化Collider时用&this->transform是没问题的——因为类成员的初始化顺序是按声明顺序来的,transform先声明会先初始化,之后collider再拿它的地址是安全的。但main里把GameObject对象push_back到vector时,如果vector容量不够,会重新分配内存,把旧元素挪到新地址,原来的Transform成员地址就失效了,Collider里的指针就成了野指针。


解决方案1:用智能指针存GameObject,避免对象拷贝

把vector的元素类型改成unique_ptr<GameObject>,让GameObject始终在堆上,地址固定,Collider里的指针永远有效:

#include <vector>
#include <memory>

struct Transform{
    float x, y;
    Transform(float x_, float y_) : x(x_), y(y_) {}
};

class Collider{
public:
    Transform* transform;
    Collider(Transform* _transform) : transform(_transform) {}

    // 示例:碰撞后更新Transform的方法
    void updateOnCollision() {
        if (transform) {
            transform->x += 1.0f;
            transform->y += 1.0f;
        }
    }
};

class GameObject{
public:
    Transform transform;
    Collider collider;

    GameObject(Transform t) : transform(t), collider(&this->transform) {}
};

int main(){
    std::vector<std::unique_ptr<GameObject>> quads;
  
    for(int i=0; i<10; i++){
        quads.push_back(std::make_unique<GameObject>(Transform(i*2.0f, i*3.0f)));
    }

    // 测试修改Transform
    quads[0]->collider.updateOnCollision();
}

解决方案2:自定义拷贝/移动函数,同步更新Collider的指针

如果一定要用值类型存GameObject,就得在拷贝、移动构造和赋值运算符里,让新对象的Collider指向自身的Transform:

#include <vector>
#include <utility> // 用于std::move

struct Transform{
    float x, y;
    Transform(float x_, float y_) : x(x_), y(y_) {}
};

class Collider{
public:
    Transform* transform;
    Collider(Transform* _transform) : transform(_transform) {}
    
    // 拷贝构造
    Collider(const Collider& other) : transform(other.transform) {}
    // 移动构造
    Collider(Collider&& other) noexcept : transform(other.transform) {
        other.transform = nullptr;
    }

    // 拷贝赋值
    Collider& operator=(const Collider& other) {
        if (this != &other) transform = other.transform;
        return *this;
    }
    // 移动赋值
    Collider& operator=(Collider&& other) noexcept {
        if (this != &other) {
            transform = other.transform;
            other.transform = nullptr;
        }
        return *this;
    }

    void updateOnCollision() {
        if (transform) {
            transform->x += 1.0f;
            transform->y += 1.0f;
        }
    }
};

class GameObject{
public:
    Transform transform;
    Collider collider;

    GameObject(Transform t) : transform(t), collider(&this->transform) {}
    
    // 拷贝构造:让新对象的collider指向自己的transform
    GameObject(const GameObject& other) : transform(other.transform), collider(&this->transform) {}
    // 移动构造:同样指向自身的transform
    GameObject(GameObject&& other) noexcept : transform(std::move(other.transform)), collider(&this->transform) {}

    // 拷贝赋值
    GameObject& operator=(const GameObject& other) {
        if (this != &other) {
            transform = other.transform;
            collider.transform = &this->transform;
        }
        return *this;
    }
    // 移动赋值
    GameObject& operator=(GameObject&& other) noexcept {
        if (this != &other) {
            transform = std::move(other.transform);
            collider.transform = &this->transform;
        }
        return *this;
    }
};

int main(){
    std::vector<GameObject> quads;
  
    for(int i=0; i<10; i++){
        quads.push_back(GameObject(Transform(i*2.0f, i*3.0f)));
    }

    quads[0].collider.updateOnCollision();
}

解决方案3:动态分配Transform,保持地址不变

用shared_ptr管理Transform,这样就算GameObject被拷贝/移动,Transform的地址也不会变:

#include <vector>
#include <memory>

struct Transform{
    float x, y;
    Transform(float x_, float y_) : x(x_), y(y_) {}
};

class Collider{
public:
    std::shared_ptr<Transform> transform;
    Collider(std::shared_ptr<Transform> _transform) : transform(_transform) {}

    void updateOnCollision() {
        if (transform) {
            transform->x += 1.0f;
            transform->y += 1.0f;
        }
    }
};

class GameObject{
public:
    std::shared_ptr<Transform> transform;
    Collider collider;

    GameObject(Transform t) : transform(std::make_shared<Transform>(t)), collider(transform) {}
};

int main(){
    std::vector<GameObject> quads;
  
    for(int i=0; i<10; i++){
        quads.push_back(GameObject(Transform(i*2.0f, i*3.0f)));
    }

    quads[0].collider.updateOnCollision();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 01:32:59