DefaultChannelResponses
DefaultChannelResponses
#Overview
name: DefaultChannelResponses
The value of this variable can be defined or overridden in .ini config files. 5
.ini config files referencing this setting variable.
It is referenced in 14
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of DefaultChannelResponses is to define game-specific overrides to default responses for collision channels in Unreal Engine 5. This variable is primarily used for customizing collision behavior in the game’s physics system.
DefaultChannelResponses is mainly utilized by the Collision Profile system, which is part of Unreal Engine’s physics module. It is heavily referenced in the CollisionProfileDetails class, which is responsible for managing and customizing collision profiles in the editor.
The value of this variable is typically set in the project’s configuration files and loaded during engine initialization. It can also be modified through the Collision editor in Unreal Engine’s project settings.
DefaultChannelResponses interacts with other collision-related variables and structures, such as FCollisionResponseContainer and FCustomProfile. It is used to populate TraceTypeMapping and ObjectTypeMapping, which are crucial for the engine’s collision system.
Developers must be aware that:
- The order of entries in DefaultChannelResponses is important, as it’s sorted and used to populate other collision-related mappings.
- Duplicate channel names are not allowed and will be removed automatically.
- The number of custom channels is limited (MAX_CUSTOMCOLLISION_CHANNEL).
Best practices when using this variable include:
- Ensure unique names for each custom channel.
- Keep the number of custom channels within the allowed limit.
- Be cautious when modifying this variable, as it can significantly impact the game’s collision behavior.
- Use the Collision editor in the project settings for easier management of custom channels and responses.
- Consider the performance implications of adding too many custom collision channels.
#Setting Variables
#References In INI files
Location: <Workspace>/Projects/Lyra/Config/DefaultEngine.ini:205, section: [/Script/Engine.CollisionProfile]
- INI Section:
/Script/Engine.CollisionProfile
- Raw value:
(Channel=ECC_GameTraceChannel1,DefaultResponse=ECR_Ignore,bTraceType=True,bStaticObject=False,Name="Lyra_TraceChannel_Interaction")
- Is Array:
True
Location: <Workspace>/Projects/Lyra/Config/DefaultEngine.ini:206, section: [/Script/Engine.CollisionProfile]
- INI Section:
/Script/Engine.CollisionProfile
- Raw value:
(Channel=ECC_GameTraceChannel2,DefaultResponse=ECR_Ignore,bTraceType=True,bStaticObject=False,Name="Lyra_TraceChannel_Weapon")
- Is Array:
True
Location: <Workspace>/Projects/Lyra/Config/DefaultEngine.ini:207, section: [/Script/Engine.CollisionProfile]
- INI Section:
/Script/Engine.CollisionProfile
- Raw value:
(Channel=ECC_GameTraceChannel3,DefaultResponse=ECR_Ignore,bTraceType=True,bStaticObject=False,Name="Lyra_TraceChannel_Weapon_Capsule")
- Is Array:
True
Location: <Workspace>/Projects/Lyra/Config/DefaultEngine.ini:208, section: [/Script/Engine.CollisionProfile]
- INI Section:
/Script/Engine.CollisionProfile
- Raw value:
(Channel=ECC_GameTraceChannel4,DefaultResponse=ECR_Ignore,bTraceType=True,bStaticObject=False,Name="Lyra_TraceChannel_Weapon_Multi")
- Is Array:
True
Location: <Workspace>/Projects/Lyra/Config/DefaultEngine.ini:209, section: [/Script/Engine.CollisionProfile]
- INI Section:
/Script/Engine.CollisionProfile
- Raw value:
(Channel=ECC_GameTraceChannel5,DefaultResponse=ECR_Ignore,bTraceType=True,bStaticObject=False,Name="Lyra_TraceChannel_AimAssist")
- Is Array:
True
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Source/Editor/DetailCustomizations/Private/CollisionProfileDetails.cpp:1839
Scope (from outer to inner):
file
function void FCollisionProfileDetails::RefreshChannelList
Source code excerpt:
TraceChannelList.Empty();
for(auto Iter = CollisionProfile->DefaultChannelResponses.CreateIterator(); Iter; ++Iter)
{
// only display game channels
if(Iter->Channel >= ECC_GameTraceChannel1 && Iter->bTraceType)
{
TraceChannelList.Add(MakeShareable(new FChannelListItem(MakeShareable(new FCustomChannelSetup(*Iter)))));
}
#Loc: <Workspace>/Engine/Source/Editor/DetailCustomizations/Private/CollisionProfileDetails.cpp:1852
Scope (from outer to inner):
file
function void FCollisionProfileDetails::RefreshChannelList
Source code excerpt:
ObjectChannelList.Empty();
for(auto Iter = CollisionProfile->DefaultChannelResponses.CreateIterator(); Iter; ++Iter)
{
// only display game channels
if(Iter->Channel >= ECC_GameTraceChannel1 && !Iter->bTraceType)
{
ObjectChannelList.Add(MakeShareable(new FChannelListItem(MakeShareable(new FCustomChannelSetup(*Iter)))));
}
#Loc: <Workspace>/Engine/Source/Editor/DetailCustomizations/Private/CollisionProfileDetails.cpp:1887
Scope (from outer to inner):
file
function void FCollisionProfileDetails::RemoveChannel
Source code excerpt:
void FCollisionProfileDetails::RemoveChannel(ECollisionChannel CollisionChannel) const
{
for(auto Iter = CollisionProfile->DefaultChannelResponses.CreateIterator(); Iter; ++Iter)
{
if(Iter->Channel == CollisionChannel)
{
CollisionProfile->DefaultChannelResponses.RemoveAt(Iter.GetIndex());
break;
}
}
}
int32 FCollisionProfileDetails::FindProfileIndexFromName(FName Name) const
#Loc: <Workspace>/Engine/Source/Editor/DetailCustomizations/Private/CollisionProfileDetails.cpp:1912
Scope (from outer to inner):
file
function FCustomChannelSetup * FCollisionProfileDetails::FindFromChannel
Source code excerpt:
FCustomChannelSetup * FCollisionProfileDetails::FindFromChannel(ECollisionChannel CollisionChannel) const
{
for(auto Iter = CollisionProfile->DefaultChannelResponses.CreateIterator(); Iter; ++Iter)
{
if(Iter->Channel == CollisionChannel)
{
return &(*Iter);
}
}
#Loc: <Workspace>/Engine/Source/Editor/DetailCustomizations/Private/CollisionProfileDetails.cpp:1925
Scope (from outer to inner):
file
function ECollisionChannel FCollisionProfileDetails::FindAvailableChannel
Source code excerpt:
ECollisionChannel FCollisionProfileDetails::FindAvailableChannel() const
{
if(CollisionProfile->DefaultChannelResponses.Num() < MAX_CUSTOMCOLLISION_CHANNEL)
{
// this is very inefficient
for(int32 ChannelIndex = ECC_GameTraceChannel1; ChannelIndex < ECC_GameTraceChannel1 + MAX_CUSTOMCOLLISION_CHANNEL; ++ChannelIndex)
{
if( FindFromChannel((ECollisionChannel)ChannelIndex) == NULL)
{
#Loc: <Workspace>/Engine/Source/Editor/DetailCustomizations/Private/CollisionProfileDetails.cpp:1942
Scope (from outer to inner):
file
function bool FCollisionProfileDetails::IsValidChannelSetup
Source code excerpt:
bool FCollisionProfileDetails::IsValidChannelSetup(const FCustomChannelSetup* Channel) const
{
for(auto Iter = CollisionProfile->DefaultChannelResponses.CreateConstIterator(); Iter; ++Iter)
{
if(Iter->Channel != Channel->Channel)
{
// make sure name isn't same
if(Iter->Name == Channel->Name)
{
#Loc: <Workspace>/Engine/Source/Editor/DetailCustomizations/Private/CollisionProfileDetails.cpp:1975
Scope (from outer to inner):
file
function bool FCollisionProfileDetails::IsNewChannelAvailable
Source code excerpt:
bool FCollisionProfileDetails::IsNewChannelAvailable() const
{
return (CollisionProfile && CollisionProfile->DefaultChannelResponses.Num() < MAX_CUSTOMCOLLISION_CHANNEL);
}
FReply FCollisionProfileDetails::OnNewChannel(bool bTraceType)
{
// find empty channel and see if we can add it.
ECollisionChannel NewChannel = FindAvailableChannel();
#Loc: <Workspace>/Engine/Source/Editor/DetailCustomizations/Private/CollisionProfileDetails.cpp:2014
Scope (from outer to inner):
file
function FReply FCollisionProfileDetails::OnNewChannel
Source code excerpt:
ensure(IsValidChannelSetup(&(ChannelEditor->ChannelSetup))))
{
CollisionProfile->DefaultChannelResponses.Add(ChannelEditor->ChannelSetup);
UpdateChannel(bTraceType);
}
}
return FReply::Handled();
}
#Loc: <Workspace>/Engine/Source/Editor/DetailCustomizations/Private/CollisionProfileDetails.cpp:2240
Scope (from outer to inner):
file
function void FCollisionProfileDetails::FCollisionProfileData::Save
Source code excerpt:
{
Profiles = Profile->Profiles;
DefaultChannelResponses = Profile->DefaultChannelResponses;
EditProfiles = Profile->EditProfiles;
}
//=====================================================================================
#undef LOCTEXT_NAMESPACE
#Loc: <Workspace>/Engine/Source/Editor/DetailCustomizations/Private/CollisionProfileDetails.h:192
Scope (from outer to inner):
file
class class FCollisionProfileDetails : public IDetailCustomization
Source code excerpt:
{
TArray<FCollisionResponseTemplate> Profiles;
TArray<FCustomChannelSetup> DefaultChannelResponses;
TArray<FCustomProfile> EditProfiles;
void Save(UCollisionProfile * Profile);
};
FCollisionProfileData SavedData;
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Classes/Engine/CollisionProfile.h:169
Scope (from outer to inner):
file
class class UCollisionProfile : public UDeveloperSettings
Source code excerpt:
/** Game-specific overrides to default responses to collision channels */
UPROPERTY(globalconfig)
TArray<FCustomChannelSetup> DefaultChannelResponses;
/** Game-specific overrides to engine profiles */
UPROPERTY(globalconfig)
TArray<FCustomProfile> EditProfiles;
/** Used to handle renaming profiles */
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Collision/CollisionProfile.cpp:373
Scope (from outer to inner):
file
function void UCollisionProfile::LoadProfileConfig
Source code excerpt:
FCollisionResponseContainer::DefaultResponseContainer.SetResponse( COLLISION_GIZMO, ECR_Ignore );
// we can't guarantee that DefaultChannelResponses was loaded ordered (from
// config) - in the following loop, we fill out TraceTypeMapping and
// ObjectTypeMapping from DefaultChannelResponses, and those mappings expect
// to be ordered (since we reinterpret the index to be an enum value itself
// in functions like ConvertToCollisionChannel(), etc.)
DefaultChannelResponses.Sort([](const FCustomChannelSetup& Rhs, const FCustomChannelSetup& Lhs)->bool
{
return (Rhs.Channel < Lhs.Channel);
}
);
for (int32 ChannelResponseIndex = 0; ChannelResponseIndex < DefaultChannelResponses.Num(); ++ChannelResponseIndex)
{
const FCustomChannelSetup& CustomChannel = DefaultChannelResponses[ChannelResponseIndex];
int32 EnumIndex = CustomChannel.Channel;
// make sure it is the range of channels we allow to change
if ( IS_VALID_COLLISIONCHANNEL(EnumIndex) )
{
if ( CustomChannel.Name != NAME_None )
{
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Collision/CollisionProfile.cpp:401
Scope (from outer to inner):
file
function void UCollisionProfile::LoadProfileConfig
Source code excerpt:
{
UE_LOG(LogCollisionProfile, Warning, TEXT("Cannot map multiple responses to the same collision channel (%d); ignoring '%s' "), EnumIndex, *DisplayValue);
DefaultChannelResponses.RemoveAt(ChannelResponseIndex);
// decrement iterator so this index gets processed again (since we just removed an entry)
--ChannelResponseIndex;
continue;
}
// also has to set this for internal use
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Collision/CollisionProfile.cpp:721
Scope (from outer to inner):
file
function void UCollisionProfile::SaveCustomResponses
Source code excerpt:
//The channel should either be a public engine channel or an existing game channel
if((Index < ECollisionChannel::ECC_EngineTraceChannel1)
|| (DefaultChannelResponses.FindByPredicate([ChannelDisplayName](const FCustomChannelSetup& ChannelSetup) { return ChannelSetup.Name == ChannelDisplayName; }) != nullptr))
{
Template.CustomResponses.Add(FResponseChannel(ChannelDisplayName, (ECollisionResponse)(Template.ResponseToChannels.EnumArray[Index])));
}
}
}
}