1. Transform으로 충돌을 판정할수있게 되었지만 충돌을 담당할 충돌체를 따로 만들어서 기능들을 사용하도록 한다.
또 그 충돌체를 관리할 충돌체그룹 클래스를 만들었다.
그리고 해당 콜리젼그룹을 레벨에서 map으로 관리해준다.
2. 콜리젼을 생성하면 Level의 PushCollsion을 통해 Collisions에 콜리젼 오더별로 들어가게 된다.
void GameEngineLevel::PushCollision(std::shared_ptr<class GameEngineCollision> _Collision)
{
if (nullptr == _Collision)
{
MsgBoxAssert("존재하지 않는 콜리전을 사용하려고 했습니다.");
return;
}
if (false == Collisions.contains(_Collision->GetOrder()))
{
Collisions[_Collision->GetOrder()] = std::make_shared<GameEngineCollisionGroup>();
}
Collisions[_Collision->GetOrder()]->PushCollision(_Collision);
}
3. 콜리젼이 충돌함수를 호출하게 되면 콜리젼그룹에있는 충돌함수로 진입하게 된다.
bool GameEngineCollision::Collision(int _Order)
{
std::shared_ptr<GameEngineCollisionGroup> OtherGroup = GetLevel()->Collisions[_Order];
return OtherGroup->Collision(GetDynamic_Cast_This<GameEngineCollision>());
}
콜리젼 그룹에서 비로소 Transform으로 충돌을 판단하게된다.
bool GameEngineCollisionGroup::Collision(std::shared_ptr<GameEngineCollision> _Collision)
{
for (std::shared_ptr<class GameEngineCollision> Collsion : Collisions)
{
if (Collsion == _Collision)
{
continue;
}
if (true == GameEngineTransform::Collision({ _Collision->Transform.ColData , Collsion->Transform.ColData, _Collision->GetCollisionType(), Collsion->GetCollisionType() }))
{
return true;
}
}
return false;
}
이런 방식으로 충돌체를 관리하고 사용하게 될것이다.
4. 충돌체에 기능들 추가
설명 - 1. 원하는 충돌체 그룹과 충돌을 했는지 판별.
2. 내가 이동할 위치에 갔다면 원하는 충돌체 그룹과 충돌을 했는지 판별.
3. 원하는 충돌체 그룹과 충돌을 했을때 어떤 녀석과 충돌했는지 얻어낼수있는지.
4. 내가 이동할 위치에 가서 원하는 충돌체 그룹과 충돌을 했을때 어떤 녀석과 충돌했는지 얻어낼수있는지.
5. 내가 처음 충돌했는지, 충돌중인지, 충돌중이다가 벗어났는지 를 판단해서 이벤트를 실행시킬수 있다.
4-1. 3번에 있는 코드가 해당 케이스이다.
4-2. 기본적으로 같으나 Center를 NextPos 만큼 이동시켜본다음 확인하는 점이 다르다.
bool GameEngineCollisionGroup::Collision(std::shared_ptr<GameEngineCollision> _Collision,
const float4& _NextPos)
{
CollisionData Data = _Collision->Transform.ColData;
Data.OBB.Center.x += _NextPos.X;
Data.OBB.Center.y += _NextPos.Y;
Data.OBB.Center.z += _NextPos.Z;
for (std::shared_ptr<class GameEngineCollision> Collsion : Collisions)
{
if (Collsion == _Collision)
{
continue;
}
if (true == GameEngineTransform::Collision({ Data , Collsion->Transform.ColData, _Collision->GetCollisionType(), Collsion->GetCollisionType() }))
{
return true;
}
}
return false;
}
4-3. 충돌한 그룹이 ResultCollision에 담기게 되고 그 ResultCollision을 _Function으로 볼수있다.
bool GameEngineCollisionGroup::Collision(std::shared_ptr<GameEngineCollision> _Collision,
std::function<void(std::vector<std::shared_ptr<GameEngineCollision>>& _Collisions)> _Function)
{
// static 지역변수로 만들면
// std::list Nodes delete를 한다.
// 쓰레드나 이런것에서 위험하지만
static std::vector<std::shared_ptr<GameEngineCollision>> ResultCollision;
ResultCollision.clear();
for (std::shared_ptr<class GameEngineCollision> Collsion : Collisions)
{
if (Collsion == _Collision)
{
continue;
}
if (true == GameEngineTransform::Collision({ _Collision->Transform.ColData , Collsion->Transform.ColData, _Collision->GetCollisionType(), Collsion->GetCollisionType() }))
{
ResultCollision.push_back(Collsion);
}
}
if (0 != ResultCollision.size())
{
_Function(ResultCollision);
}
return false;
}
테스트 코드
충돌한 충돌체를 얻었고 그 충돌체의 액터를 얻어서 Death 시키면 죽게된다.
Col->Collision(ContentsCollisionType::Monster, {100.0f, 0.0f, 0.0f}, [](std::vector<std::shared_ptr<GameEngineCollision>>& _Collision)
{
for (size_t i = 0; i < _Collision.size(); i++)
{
_Collision[i]->GetActor()->Death();
}
});
4-4. NextPos만 추가되고 동일.
4-5.
bool GameEngineCollisionGroup::CollisionEvent(std::shared_ptr<GameEngineCollision> _Collision, const EventParameter& _Event)
{
static std::vector<std::shared_ptr<GameEngineCollision>> ResultCollision;
ResultCollision.clear();
for (std::shared_ptr<class GameEngineCollision> Collsion : Collisions)
{
if (Collsion == _Collision)
{
continue;
}
if (true == GameEngineTransform::Collision({ _Collision->Transform.ColData , Collsion->Transform.ColData, _Collision->GetCollisionType(), Collsion->GetCollisionType() }))
{
ResultCollision.push_back(Collsion);
continue;
}
GameEngineCollision* Other = Collsion.get();
// 애는 충돌을 나랑 안했네.
// 그런데 충돌을 했던적이 있네? ===> 충돌중이다가 충돌벗어남.
if (true == _Collision->Others.contains(Other))
{
if (_Event.Exit)
{
_Event.Exit(Other);
Other->Others.erase(Other);
_Collision->Others.erase(Other);
}
}
}
if (0 != ResultCollision.size())
{
// ResultCollision 나랑 충돌한 애들.
for (size_t i = 0; i < ResultCollision.size(); i++)
{
GameEngineCollision* Other = ResultCollision[i].get();
// 나랑 충돌을 처음했다. ===> 충돌 첫진입.
if (false == _Collision->Others.contains(Other))
{
if (_Event.Enter)
{
_Event.Enter(Other);
Other->Others.insert(Other);
_Collision->Others.insert(Other);
}
}
else // 나랑 충돌을 처음한게 아니고 충돌했다. ==> 충돌중이다.
{
if (_Event.Stay)
{
_Event.Stay(Other);
}
}
}
}
return false;
}
4-5 테스트 코드.
EventParameter를 만들고 Enter, Stayn, Exit를 채워주면 해당 기능들을 호출하는 함수를 간단히 만들수있고
그 Event를 토대로 함수를 호출하면 된다.
EventParameter Event;
Event.Enter = [](GameEngineCollision* Col)
{
int a = 0;
};
Event.Stay = [](GameEngineCollision* Col)
{
int a = 0;
};
Event.Exit = [](GameEngineCollision* Col)
{
Col->GetActor()->Death();
int a = 0;
};
Col->CollisionEvent(ContentsCollisionType::Monster, Event);
'오늘 하루' 카테고리의 다른 글
9월 18일 엔진 업데이트 - 마우스 월드포스. (0) | 2023.09.18 |
---|---|
9월 8일. 이미지트랜스폼 추가, 피봇 추가 (0) | 2023.09.08 |
9월 6일. 쿼터니온과 충돌판별 (0) | 2023.09.06 |
9월 5일 (0) | 2023.09.06 |
9월 1일. (0) | 2023.09.01 |