[BlackPearl引擎开发记录 3] -- 对象析构注意点

记录一下今天写的bug = =:析构顺序不正确导致abort()异常 (析构了栈上的变量,这个变量含有生命周期比他长的类的成员变量)

代码如下:

class EntityTestLayer :public BlackPearl::Layer {
public:

	EntityTestLayer(const std::string& name, BlackPearl::SystemManager *systemManager, BlackPearl::EntityManager *entityManager)
		: Layer(name, systemManager, entityManager)
	{
		//	BlackPearl::Object *m_CameraObj;

		BlackPearl::Entity *entity = entityManager->CreateEntity();
		BlackPearl::Object CameraObj(entity->GetEntityManager(), entity->GetId());
		m_CameraComponent = CameraObj.AddComponent<BlackPearl::PerspectiveCamera>();

		m_CameraComponent->SetPosition(glm::vec3(0.0f, 0.0f, 8.0f));
		m_CameraPosition = m_CameraComponent->GetPosition();
		m_CameraRotation.Yaw = m_CameraComponent->Yaw();
		m_CameraRotation.Pitch = m_CameraComponent->Pitch();

		glm::vec3 pointLightPositions[] = {
		glm::vec3(2.3f,  0.2f,  2.0f),
		glm::vec3(2.3f, -3.3f, -4.0f),
		glm::vec3(-2.7f,  3.0f, -7.5f),
		//glm::vec3(-4.0f,  2.0f, -12.0f),
		};
		std::vector<BlackPearl::Light::Props> pointLightProps = {
		{{0.2f, 0.2f, 0.2f},{ 1.0f, 0.2f, 0.1f},{1.0f, 1.0f, 1.0f}},
		{{0.2f, 0.2f, 0.2f},{ 0.2f, 1.0f, 0.1f},{1.0f, 1.0f, 1.0f}},
		{{0.2f, 0.2f, 0.2f},{ 0.1f, 0.2f, 1.0f},{1.0f, 1.0f, 1.0f}}
		};
		for (int i = 0; i < 1; i++)
		{
			BlackPearl::Entity* lightEntity = entityManager->CreateEntity();
			BlackPearl::Object LightObj(lightEntity->GetEntityManager(), lightEntity->GetId());


			auto ptr = LightObj.AddComponent<BlackPearl::PointLight>();
			m_LightComponent.reset(ptr);
			m_LightComponent->SetProps(pointLightProps[0]);
			std::dynamic_pointer_cast<BlackPearl::PointLight>(m_LightComponent)->SetPosition(pointLightPositions[0]);

			std::dynamic_pointer_cast<BlackPearl::PointLight>(m_LightComponent)->SetAttenuation(BlackPearl::PointLight::Attenuation(3250));

			m_LightSources.AddLight(m_LightComponent);
		}

		BlackPearl::Renderer::Init();
		std::cout << "_______________________" << std::endl;
		/*systemManager->Add<InputSystem>();
		systemManager->Add<RenderSystem>();
		systemManager->Configure();*/

	}

 //。。。。。。
private:
	BlackPearl::LightSources m_LightSources;
	std::shared_ptr<BlackPearl::Light> m_LightComponent;
	BlackPearl::Camera* m_CameraComponent;
	glm::vec3 m_CameraPosition = { 0.0f,0.0f,0.0f };
	struct CameraRotation {
		float Yaw;
		float Pitch;

	};
	CameraRotation m_CameraRotation;
	float m_LastMouseX;
	float m_LastMouseY;
	float m_CameraMoveSpeed = 5.0f;
	float m_CameraRotateSpeed = 9.0f;

};

当退出for循环时触发异常:

AddComponent函数把 m_LightComponent添加到LightObj

		template<typename C, typename ...Args>
		C* AddComponent(Args ...args)
		{
			//GE_ASSERT(Valid(), "invalid entity" + std::to_string(m_Id.index())); //TODO::https://bbs.csdn.net/topics/391862079
			//C* component = m_EntityManager->AddComponent(m_Id, args);

			const BaseComponent::Family family = GetComponentFamliy<C>();
			//Returns whether the bit at family pos is set (i.e., whether it is one).
			GE_ASSERT(!m_ComponentMask.test(family), "Component already existed!")


				m_ComponentMask.set(family);

			//所有的component都用Create实例化-->方便子类继承!
			//C* component = C::Create(m_EntityManager, m_Id, std::forward<Args>(args)...);
			C* component = DBG_NEW C(m_EntityManager, m_Id, std::forward<Args>(args)...);
			m_Components.insert(std::make_pair(C::Famliy(), component));
			return component;

		}

异常的原因是:LightObj是一个栈上分配的变量,LightObj所含有的 m_LightComponet 是EntityTestLayer 这个类的成员变量,

当退出for循环是 LightObj会被析构!

	virtual ~Object() {
		Destroy();
	};

    void Object::Destroy()
	{
		for (auto& pair : m_Components) { //TODO::看一下要不要用智能指针
			BaseComponent* component = pair.second;
			delete component;
			component = nullptr;
		}
		m_ComponentMask.reset();
		m_EntityManager->DestroyEntity(m_Id);	
		m_Components.clear();
	}

它所含有的 components都会被delete掉,而 m_LightComponent由于是成员变量,它的生命周期是随着类的销毁而销毁的!而退出for循环时类EntityTestLayer 依旧存在,所以在析构栈上的LightObj时就会发生异常!!同理CameraObj也一样!

 

修复后的代码:

class EntityTestLayer :public BlackPearl::Layer {
public:

	EntityTestLayer(const std::string& name, BlackPearl::SystemManager *systemManager, BlackPearl::EntityManager *entityManager)
		: Layer(name, systemManager, entityManager)
	{
		//	BlackPearl::Object *m_CameraObj;

		BlackPearl::Entity *entity = entityManager->CreateEntity();
		m_CameraObj = new BlackPearl::Object(entity->GetEntityManager(), entity->GetId());
		m_CameraComponent = m_CameraObj->AddComponent<BlackPearl::PerspectiveCamera>();
		//m_CameraComponent = CameraObj.AddComponent<BlackPearl::PerspectiveCamera>();

		m_CameraComponent->SetPosition(glm::vec3(0.0f, 0.0f, 8.0f));
		m_CameraPosition = m_CameraComponent->GetPosition();
		m_CameraRotation.Yaw = m_CameraComponent->Yaw();
		m_CameraRotation.Pitch = m_CameraComponent->Pitch();


		glm::vec3 pointLightPositions[] = {
		glm::vec3(2.3f,  0.2f,  2.0f),
		glm::vec3(2.3f, -3.3f, -4.0f),
		glm::vec3(-2.7f,  3.0f, -7.5f),
		//glm::vec3(-4.0f,  2.0f, -12.0f),
		};
		std::vector<BlackPearl::Light::Props> pointLightProps = {
		{{0.2f, 0.2f, 0.2f},{ 1.0f, 0.2f, 0.1f},{1.0f, 1.0f, 1.0f}},
		{{0.2f, 0.2f, 0.2f},{ 0.2f, 1.0f, 0.1f},{1.0f, 1.0f, 1.0f}},
		{{0.2f, 0.2f, 0.2f},{ 0.1f, 0.2f, 1.0f},{1.0f, 1.0f, 1.0f}}
		};
		for (int i = 0; i < 1; i++)
		{
			BlackPearl::Entity* lightEntity = entityManager->CreateEntity();
			m_LightObj = new BlackPearl::Object(lightEntity->GetEntityManager(), lightEntity->GetId());


			auto ptr = m_LightObj->AddComponent<BlackPearl::PointLight>();
			m_LightComponent.reset(ptr);
			m_LightComponent->SetProps(pointLightProps[0]);
			std::dynamic_pointer_cast<BlackPearl::PointLight>(m_LightComponent)->SetPosition(pointLightPositions[0]);

			std::dynamic_pointer_cast<BlackPearl::PointLight>(m_LightComponent)->SetAttenuation(BlackPearl::PointLight::Attenuation(3250));

			m_LightSources.AddLight(m_LightComponent);
		}

		BlackPearl::Renderer::Init();
		std::cout << "_______________________" << std::endl;
		/*systemManager->Add<InputSystem>();
		systemManager->Add<RenderSystem>();
		systemManager->Configure();*/

	}


	void OnUpdate(BlackPearl::Timestep ts) override {

		//m_SystemManager->Update<InputSystem>(ts);
		//m_SystemManager->Update<RenderSystem>(ts);
		InputCheck(ts);

		// render
		BlackPearl::RenderCommand::SetClearColor({ 0.0f,0.0f,0.0f,0.0f });
		//m_Shader->Bind();


		BlackPearl::Renderer::BeginScene(*m_CameraComponent, m_LightSources);
	}

	void OnImguiRender() override {

		ImGui::Begin("Settings");
		ImGui::Text("Hello World");
		ImGui::End();


	}
	void OnAttach() override {


	}
	void InputCheck(float ts)
	{
		if (BlackPearl::Input::IsKeyPressed(BP_KEY_W)) {
			m_CameraPosition += m_CameraComponent->Front() * m_CameraMoveSpeed * ts;
		}
		else if (BlackPearl::Input::IsKeyPressed(BP_KEY_S)) {
			m_CameraPosition -= m_CameraComponent->Front()* m_CameraMoveSpeed * ts;
		}
		if (BlackPearl::Input::IsKeyPressed(BP_KEY_A)) {
			m_CameraPosition -= m_CameraComponent->Right() * m_CameraMoveSpeed * ts;
		}
		else if (BlackPearl::Input::IsKeyPressed(BP_KEY_D)) {
			m_CameraPosition += m_CameraComponent->Right() * m_CameraMoveSpeed * ts;

		}
		if (BlackPearl::Input::IsKeyPressed(BP_KEY_E)) {
			m_CameraPosition -= m_CameraComponent->Up() * m_CameraMoveSpeed * ts;
		}
		else if (BlackPearl::Input::IsKeyPressed(BP_KEY_Q)) {
			m_CameraPosition += m_CameraComponent->Up() * m_CameraMoveSpeed * ts;

		}
		// ---------------------Rotation--------------------------------------

		float posx = BlackPearl::Input::GetMouseX();
		float posy = BlackPearl::Input::GetMouseY();
		if (BlackPearl::Input::IsMouseButtonPressed(BP_MOUSE_BUTTON_RIGHT)) {


			if (BlackPearl::Input::IsFirstMouse()) {
				BlackPearl::Input::SetFirstMouse(false);
				m_LastMouseX = posx;
				m_LastMouseY = posy;
			}
			float diffx = posx - m_LastMouseX;
			float diffy = -posy + m_LastMouseY;

			m_LastMouseX = posx;
			m_LastMouseY = posy;
			m_CameraRotation.Yaw += diffx * m_CameraRotateSpeed * ts;
			m_CameraRotation.Pitch += diffy * m_CameraRotateSpeed * ts;

			if (m_CameraRotation.Pitch > 89.0f)
				m_CameraRotation.Pitch = 89.0f;
			if (m_CameraRotation.Pitch < -89.0f)
				m_CameraRotation.Pitch = -89.0f;

			m_CameraComponent->SetRotation(m_CameraRotation.Yaw, m_CameraRotation.Pitch);

		}
		else {

			m_LastMouseX = posx;//lastMouse时刻记录当前坐标位置,防止再次点击右键时,发生抖动!
			m_LastMouseY = posy;
		}


		m_CameraComponent->SetPosition(m_CameraPosition);
	}
private:
	BlackPearl::LightSources m_LightSources;
	BlackPearl::Object *m_LightObj;
	BlackPearl::Object *m_CameraObj;
	std::shared_ptr<BlackPearl::Light> m_LightComponent;
	BlackPearl::Camera* m_CameraComponent;

	glm::vec3 m_CameraPosition = { 0.0f,0.0f,0.0f };
	struct CameraRotation {
		float Yaw;
		float Pitch;

	};
	CameraRotation m_CameraRotation;
	float m_LastMouseX;
	float m_LastMouseY;
	float m_CameraMoveSpeed = 5.0f;
	float m_CameraRotateSpeed = 9.0f;

};

成功跑通:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值