Hello all! This is in C++, and the code you see below is actually setup in my Character class in which I derive all my characters from, but you can move it other classes (I recommend creating a base class with this code in it that way, you can check the lighting condition of any object derived from that base class).
H:
virtual void Tick(float DeltaSeconds) override;
/* Handle Light Detection */
void HandleLightDetection();
/* Does this character look for light? */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Character")
bool bCheckLightingCondition;
/* Is this character in light? */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Character")
bool bIsInLight;
CPP:
void AABCharacter::Tick(float DeltaSeconds)
{
// Call Super::Tick,
Super::Tick(DeltaSeconds);
// Handle Light Detection.
HandleLightDetection();
}
/* Handle Light Detection */
void AABCharacter::HandleLightDetection()
{
// If "CheckLightingCondition" is true,
if (bCheckLightingCondition)
{
// Write "bIsInLight" to the screen as a message,
GEngine->AddOnScreenDebugMessage(-1, 5, FColor::Yellow, FString::FromInt(bIsInLight));
// Create a bool that will tell if any light is actually affecting the player or if the player is in any of the lights,
bool lit = false;
// [THANKS TO FOR THE ARTICLE ABOUT THIS! :D] For every light component,
for (TObjectIterator<ULightComponent> Itr; Itr; ++Itr)
{
// THANKS TO N00854180T FOR MAKING THE CODE SO MUCH NEATER :D //
// If this light is enabled (or visible),
if (!Itr->IsVisible())
continue;
// If the light type is not directional,
if (Itr->GetLightType() == LightType_Directional)
continue;
// If the light affects this character's capsule component,
if (!Itr->AffectsPrimitive(CapsuleComponent))
continue;
// If a line trace test from the light's position to the character's position does not hit any actor,
if (GetWorld()->LineTraceTest(Itr->GetComponentLocation(), GetActorLocation(), ECC_Visibility, FCollisionQueryParams(true)))
continue;
// Draw a Debug Line to show how the light is hitting the player,
DrawDebugLine(GetWorld(), Itr->GetComponentLocation(), GetActorLocation(), FColor::Yellow);
// The player is in light, so set "lit" to true.
lit = true;
}
// If "lit",
if (lit)
{
// Set "bIsInLight" to true,
bIsInLight = true;
// And prevent "bIsInLight" from being set to false by returning.
return;
}
// Only set to false if "lit" is not equal to true.
bIsInLight = false;
}
}
You can remove the line where I check if the light is not a directional light if needed. I only have that there because I don’t want it to check directional lights. I have not really looked to see if there was a way to do this in blueprint (because you can’t really iterate through every light component unless you use “Get All Actors of Type” which can be slow when called every frame), but you can try it if you want. You can remove the lines with the stars, although I recommend that you try the code out first before doing so. I only had those there to make sure it was working correctly. And there you go! When the actor being checked is in light, “bIsInLight” will be equal to true. One more thing! In my constructor for my playable character class (which is derived from my base character class), I set “bCheckLightingCondition” to true. I created that variable so I can control which types of characters should check if they are in light. Here are some images of the result (NOTE: I have not built lighting again yet so the shadows look weird):
http://imageshack.com/scaled/large/661/4M3IeV.png
http://imageshack.com/scaled/large/539/AXmBQf.png
http://imageshack.com/scaled/large/905/udyoMT.png
That little spotlight right there is actually a flashlight, lol
http://imageshack.com/scaled/large/910/0GTJuL.png
Now I’m running in front of the flashlight
http://imageshack.com/scaled/large/743/MXAmXI.png
Anyways, I just thought this was pretty cool and I hope this will be useful to someone! Later!