게임 개발/[D2D_Portfolio] DirectX2D 포트폴리오 작업일지

9. Collision Callback 구현 & Tile Tool Erase 기능 구현

헛둘이 2023. 3. 22. 18:59

Collision Callback 구현

- Notification을 함수에서 전달 받았으면, 이 Notification을 통해 실제 GameObject에 통지해주어야 한다.

- 이를 위해 GameObject의 Collider 컴포넌트에서 OnCollision을 구현해서 처리를 해주었다.

- 이전 포트폴리오에서는 OnCollisionEnter, OnCollision, OnCollisionExit으로 구현했는데, 아마 이번에도 비슷하게 구현하게되지 않을까 싶다.

 

void ContactCallback::onContact(const PxContactPairHeader& pairHeader, const PxContactPair* pPairs, PxU32 iNbPairs)
{
	for (PxU32 i = 0; i < iNbPairs; i++)
	{
		const PxContactPair& cp = pPairs[i];

		if (cp.events & PxPairFlag::eNOTIFY_TOUCH_FOUND)
		{
			if (pairHeader.actors[0]->userData && pairHeader.actors[1]->userData)
			{
				GameObject* pFirst =  static_cast<GameObject*>(pairHeader.actors[0]->userData);
				GameObject* pSecond = static_cast<GameObject*>(pairHeader.actors[1]->userData);

				if (pFirst->GetCollider())
					pFirst->GetCollider()->OnCollision(pSecond->GetCollider());
			}
		}
	}
}

- 두 개의 게임 오브젝트 각각에 OnCollision을 전달하려 했으나, 경고가 발생했다. (RaceCondition)

- RaceCondition이 발생한 이유는 onContact가 병렬로 실행되어 처리되기 때문이다.

- 삽질 후에 알아낸 결과는 하나의 스레드 내에서 적용할 수 있는 물리적 작업(특정 위치에 힘을 가하거나 특정 Actor의 속도를 변경하는 등의 작업)은 하나밖에 처리할 수 없다는 것이다

- 실제로 OnCollision 함수 내에서는 물리적인 작업이 이루어져야 하는데,

- pFirst->GetCollider()->OnCollision(pSecond->GetCollider())

- pSecond->GetCollider()->OnCollision(pFirst->GetCollider()) 

- 하나의 스레드 내에서 이렇게 2개의 OnCollision()이 호출되게 되면, 경고가 발생했다.

- 경고만 뜨고 실행은 되지만 추후 문제가 될 수 있다고 판단하여 일단 하나만 호출하도록 변경(추후 해결 예정)

 


Tile Tool Erase 기능 구현

- 타일을 지우는 기능 구현

- 마우스 클릭 좌표(스크린 좌표)를 월드 좌표로 변환한 후, 타일 간격에 맞게 좌표를 변환해주는데,

- 타일 맵 map<Vec3, bool> 형태로 저장해서 해당 좌표에 타일이 존재하는지 여부를 bool 값으로 확인할 수 있게 했다.

using TileMap = std::map<Vec3, bool>;
TileMap m_mTileMap;
bool ToolScene::CheckTileAtClick(Vec3 vWorldPos)
{
	vWorldPos.x = static_cast<float>(static_cast<int32>((vWorldPos.x / TILE_SIZE)) * TILE_SIZE);
	vWorldPos.y = static_cast<float>(static_cast<int32>((vWorldPos.y / TILE_SIZE)) * TILE_SIZE);

	auto iter = m_mTileMap.find(vWorldPos);
	if (m_mTileMap.end() == iter)
		return false;

	else
		return m_mTileMap[vWorldPos];
}

- 이 기능을 구현하면서, 타일을 Dragging 방식으로 생성할 때 같은 자리에 또 생성하지 않도록 하는 로직도 추가하였음

 

 

내일 할 일

- Tile과 Player의 상호작용 (Tile은 정적 Actor로 물리세계에 존재하도록 해야 함)

- Tile과 Monster의 상호작용