Fixes for seed planting
This commit is contained in:
@@ -196,6 +196,7 @@ GlobalSettingsDataSheet=/Game/GameData/CSV/GlobalKeyValueSettings.GlobalKeyValue
|
||||
ItemSeedCarouselClass=None
|
||||
RemovableStaticMeshClass=/Script/Engine.BlueprintGeneratedClass'/Game/Prefabs/BP_RemovableStaticMeshActor.BP_RemovableStaticMeshActor_C'
|
||||
MovementDisableEffectClass=/Script/Engine.BlueprintGeneratedClass'/Game/Blueprints/GameEffects/GSE_MovementDisabled.GSE_MovementDisabled_C'
|
||||
SpriteShadowMaterial=/Game/Materials/Sprite/MI_SpriteShadow_Inst.MI_SpriteShadow_Inst
|
||||
|
||||
[/Script/InteractionSystem.InteractionSettings]
|
||||
DefaultInteractionWidgetClass=/Script/UMG.WidgetBlueprintGeneratedClass'/Game/UI/InteractionUI/WBP_Eleri_Interaction.WBP_Eleri_Interaction_C'
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Content/VFX/NI_CropReady.uasset
LFS
BIN
Content/VFX/NI_CropReady.uasset
LFS
Binary file not shown.
Binary file not shown.
@@ -10,14 +10,33 @@ void UEleriFlipbookComponent::BeginPlay()
|
||||
Super::BeginPlay();
|
||||
|
||||
DecalComponent = NewObject<UDecalComponent>(GetOwner(), UDecalComponent::StaticClass(), TEXT("Shadow Decal"));
|
||||
DecalComponent->SetDecalMaterial(DecalMaterial);
|
||||
DecalComponent->DecalSize = DecalSize;
|
||||
DecalComponent->SetFadeScreenSize(0.f);
|
||||
DecalComponent->SetupAttachment(GetOwner()->GetRootComponent());
|
||||
DecalComponent->RegisterComponent();
|
||||
DecalComponent->SetRelativeLocation(DecalOffset - FVector(0.f, 0.f, DecalSize.Z));
|
||||
UpdateRelativeLocation(FVector::ZeroVector);
|
||||
DecalComponent->SetUsingAbsoluteRotation(true);
|
||||
DecalComponent->SetRelativeRotation(FRotator(-90.f, 0.f, 0.f));
|
||||
|
||||
SetCastShadow(false);
|
||||
|
||||
if (DecalMaterial.IsValid())
|
||||
{
|
||||
DecalComponent->SetDecalMaterial(DecalMaterial.Get());
|
||||
}
|
||||
else
|
||||
{
|
||||
DecalMaterial.LoadAsync(FLoadSoftObjectPathAsyncDelegate::CreateWeakLambda(this, [this](const FSoftObjectPath& Path, UObject* MaterialObj)
|
||||
{
|
||||
if (UMaterialInterface* Interface = Cast<UMaterialInterface>(MaterialObj))
|
||||
{
|
||||
DecalComponent->SetDecalMaterial(Interface);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
void UEleriFlipbookComponent::UpdateRelativeLocation(const FVector& NewLoc) const
|
||||
{
|
||||
DecalComponent->SetRelativeLocation(NewLoc + (DecalOffset - FVector(0.f, 0.f, DecalSize.Z)));
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@ class PROJECTELERI_API UEleriFlipbookComponent : public UPaperFlipbookComponent
|
||||
public:
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
UMaterialInterface* DecalMaterial = nullptr;
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
|
||||
TSoftObjectPtr<UMaterialInterface> DecalMaterial = nullptr;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
FVector DecalSize = FVector::OneVector;
|
||||
@@ -24,9 +24,9 @@ public:
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
FVector DecalOffset = FVector::ZeroVector;
|
||||
|
||||
protected:
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly)
|
||||
UDecalComponent* DecalComponent = nullptr;
|
||||
|
||||
// Will provide a new relative location that we will update with the offset
|
||||
void UpdateRelativeLocation(const FVector& NewLoc) const;
|
||||
};
|
||||
|
||||
44
Source/ProjectEleri/Components/EleriPaperSpriteComponent.cpp
Normal file
44
Source/ProjectEleri/Components/EleriPaperSpriteComponent.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "EleriPaperSpriteComponent.h"
|
||||
|
||||
#include "Components/DecalComponent.h"
|
||||
|
||||
|
||||
void UEleriPaperSpriteComponent::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
DecalComponent = NewObject<UDecalComponent>(GetOwner(), UDecalComponent::StaticClass(), TEXT("Shadow Decal"));
|
||||
DecalComponent->DecalSize = DecalSize;
|
||||
DecalComponent->SetFadeScreenSize(0.f);
|
||||
DecalComponent->SetupAttachment(GetOwner()->GetRootComponent());
|
||||
DecalComponent->RegisterComponent();
|
||||
UpdateRelativeLocation(FVector::ZeroVector);
|
||||
DecalComponent->SetUsingAbsoluteRotation(true);
|
||||
DecalComponent->SetRelativeRotation(FRotator(-90.f, 0.f, 0.f));
|
||||
|
||||
SetCastShadow(false);
|
||||
|
||||
if (DecalMaterial.IsValid())
|
||||
{
|
||||
DecalComponent->SetDecalMaterial(DecalMaterial.Get());
|
||||
}
|
||||
else
|
||||
{
|
||||
DecalMaterial.LoadAsync(FLoadSoftObjectPathAsyncDelegate::CreateWeakLambda(this, [this](const FSoftObjectPath& Path, UObject* MaterialObj)
|
||||
{
|
||||
if (UMaterialInterface* Interface = Cast<UMaterialInterface>(MaterialObj))
|
||||
{
|
||||
DecalComponent->SetDecalMaterial(Interface);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
void UEleriPaperSpriteComponent::UpdateRelativeLocation(const FVector& NewLoc) const
|
||||
{
|
||||
DecalComponent->SetRelativeLocation(NewLoc + (DecalOffset - FVector(0.f, 0.f, DecalSize.Z)));
|
||||
}
|
||||
|
||||
32
Source/ProjectEleri/Components/EleriPaperSpriteComponent.h
Normal file
32
Source/ProjectEleri/Components/EleriPaperSpriteComponent.h
Normal file
@@ -0,0 +1,32 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "PaperSpriteComponent.h"
|
||||
#include "EleriPaperSpriteComponent.generated.h"
|
||||
|
||||
|
||||
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
|
||||
class PROJECTELERI_API UEleriPaperSpriteComponent : public UPaperSpriteComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
|
||||
TSoftObjectPtr<UMaterialInterface> DecalMaterial = nullptr;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
FVector DecalSize = FVector::OneVector;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||
FVector DecalOffset = FVector::ZeroVector;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly)
|
||||
UDecalComponent* DecalComponent = nullptr;
|
||||
|
||||
// Will provide a new relative location that we will update with the offset
|
||||
void UpdateRelativeLocation(const FVector& NewLoc) const;
|
||||
};
|
||||
@@ -12,11 +12,15 @@
|
||||
#include "Engine/StaticMesh.h"
|
||||
#include "Engine/World.h"
|
||||
#include "ItemContainer.h"
|
||||
#include "NiagaraComponent.h"
|
||||
#include "PaperSpriteComponent.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "Kismet/KismetMaterialLibrary.h"
|
||||
#include "Materials/MaterialInstanceDynamic.h"
|
||||
#include "Materials/MaterialInterface.h"
|
||||
#include "ProjectEleri/Components/EleriPaperSpriteComponent.h"
|
||||
#include "ProjectEleri/Settings/EleriGameSettings.h"
|
||||
#include "NiagaraComponent.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -31,14 +35,14 @@ namespace
|
||||
}
|
||||
|
||||
/** Slots are created at runtime as well, so the components are created with stable, deterministic names */
|
||||
UPaperSpriteComponent* CreatePaperSpriteComponent(AActor* Owner, USceneComponent* AttachParent, FName ComponentName, TSoftObjectPtr<UMaterialInterface> Material)
|
||||
UEleriPaperSpriteComponent* CreatePaperSpriteComponent(AActor* Owner, USceneComponent* AttachParent, FName ComponentName, TSoftObjectPtr<UMaterialInterface> Material)
|
||||
{
|
||||
if (!IsValid(Owner) || !IsValid(AttachParent))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UPaperSpriteComponent* SpriteComponent = NewObject<UPaperSpriteComponent>(Owner, ComponentName);
|
||||
UEleriPaperSpriteComponent* SpriteComponent = NewObject<UEleriPaperSpriteComponent>(Owner, ComponentName);
|
||||
if (!SpriteComponent)
|
||||
{
|
||||
return nullptr;
|
||||
@@ -46,10 +50,15 @@ namespace
|
||||
|
||||
SpriteComponent->SetMobility(EComponentMobility::Movable);
|
||||
SpriteComponent->SetupAttachment(AttachParent);
|
||||
SpriteComponent->DecalSize = FVector(150.f);
|
||||
SpriteComponent->DecalOffset = FVector(0.f, 0.f, 40.f);
|
||||
SpriteComponent->DecalMaterial = UEleriGameSettings::GetEleriGameSettings()->SpriteShadowMaterial;
|
||||
SpriteComponent->SetReceivesDecals(false);
|
||||
SpriteComponent->RegisterComponent();
|
||||
SpriteComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision);
|
||||
SpriteComponent->SetVisibility(false);
|
||||
TWeakObjectPtr<UPaperSpriteComponent> SpriteComp = SpriteComponent;
|
||||
SpriteComponent->DecalComponent->SetVisibility(false);
|
||||
TWeakObjectPtr<UEleriPaperSpriteComponent> SpriteComp = SpriteComponent;
|
||||
if (Material.IsValid())
|
||||
{
|
||||
SpriteComp->SetMaterial(0, Material.Get());
|
||||
@@ -265,7 +274,7 @@ void ASeedBedActor::AdvanceSeedBedByHours(int32 Hours)
|
||||
// Every hour is applied on its own, a jump over several of them grows, dries and kills hour by hour
|
||||
for (int32 HourIndex = 0; HourIndex < Hours && SlotHasLivingPlant(SlotPair.Value); ++HourIndex)
|
||||
{
|
||||
ApplyHourPassedToSlot(SlotPair.Value, Now);
|
||||
ApplyHourPassedToSlot(SlotPair.Value, Now, SlotPair.Key);
|
||||
}
|
||||
|
||||
if (bWasAlive && !SlotHasLivingPlant(SlotPair.Value))
|
||||
@@ -283,10 +292,15 @@ void ASeedBedActor::AdvanceSeedBedByHours(int32 Hours)
|
||||
}
|
||||
}
|
||||
|
||||
void ASeedBedActor::ApplyHourPassedToSlot(FSeedBedSeedSlot& Slot, const FTimeOfDayData& Now)
|
||||
void ASeedBedActor::ApplyHourPassedToSlot(FSeedBedSeedSlot& Slot, const FTimeOfDayData& Now, const FIntVector2& SlotCoordinate)
|
||||
{
|
||||
FSeedBedSeedSlotData& SlotData = Slot.SlotData;
|
||||
|
||||
if (SlotData.bBloomed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// The moisture of the soil drains with every in game hour, so the wetness is a clock of its own
|
||||
const bool bWasMoist = SlotData.MoistureHoursRemaining > 0;
|
||||
SlotData.MoistureHoursRemaining = FMath::Max(0, SlotData.MoistureHoursRemaining - 1);
|
||||
@@ -308,6 +322,11 @@ void ASeedBedActor::ApplyHourPassedToSlot(FSeedBedSeedSlot& Slot, const FTimeOfD
|
||||
}
|
||||
|
||||
SlotData.SeedAgeHours = FMath::Min(SlotData.SeedAgeHours + 1, FMath::Max(0, SlotData.GrowTime) * SeedBedHoursPerDay);
|
||||
SlotData.bBloomed = SlotData.SeedAgeHours >= SlotData.GrowTime * SeedBedHoursPerDay;
|
||||
if (SlotData.bBloomed)
|
||||
{
|
||||
RefreshSlotVisual(SlotCoordinate);
|
||||
}
|
||||
}
|
||||
|
||||
void ASeedBedActor::ApplyOfflineProgression()
|
||||
@@ -605,6 +624,18 @@ FSeedBedSeedSlot& ASeedBedActor::CreateSlot(FIntVector2 SlotCoordinate, bool bRe
|
||||
Slot.PlantSprite = CreatePaperSpriteComponent(this, GetRootComponent(), GetSlotComponentName(SlotCoordinate, TEXT("Plant")), DefaultPlantSpriteMaterial);
|
||||
}
|
||||
|
||||
Slot.NiagaraComponent = NewObject<UNiagaraComponent>(this, GetSlotComponentName(SlotCoordinate, TEXT("Vfx")));
|
||||
Slot.NiagaraComponent->SetMobility(EComponentMobility::Movable);
|
||||
Slot.NiagaraComponent->SetupAttachment(GetRootComponent());
|
||||
Slot.NiagaraComponent->SetAutoActivate(false);
|
||||
Slot.NiagaraComponent->RegisterComponent();
|
||||
Slot.NiagaraComponent->SetRelativeLocation(FVector(
|
||||
Offset.X + X + SeedBedDecalSize.Z,
|
||||
Offset.Y + Y + SeedBedDecalSize.Y,
|
||||
50.f));
|
||||
Slot.NiagaraComponent->SetVisibility(false);
|
||||
AddInstanceComponent(Slot.NiagaraComponent);
|
||||
|
||||
ApplySlotVisuals(SlotCoordinate, Slot);
|
||||
|
||||
return Slot;
|
||||
@@ -638,6 +669,7 @@ void ASeedBedActor::ApplySlotVisuals(FIntVector2 SlotCoordinate, FSeedBedSeedSlo
|
||||
{
|
||||
// A plant that died or was harvested keeps its mesh, the slot is only emptied when it is cleared for real
|
||||
Slot.PlantSprite->SetVisibility(false);
|
||||
Slot.PlantSprite->DecalComponent->SetVisibility(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -645,6 +677,13 @@ void ASeedBedActor::ApplySlotVisuals(FIntVector2 SlotCoordinate, FSeedBedSeedSlo
|
||||
FVector PlantScale = FVector(5.f);
|
||||
|
||||
const int32 StageIndex = ResolveGrowthStageIndex(Slot);
|
||||
if (StageIndex == INDEX_NONE)
|
||||
{
|
||||
Slot.PlantSprite->SetVisibility(false);
|
||||
Slot.PlantSprite->DecalComponent->SetVisibility(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const UItemDataAsset* SeedData = Slot.SlotData.ItemDataAsset;
|
||||
if (IsValid(SeedData) && SeedData->SeedStages.IsValidIndex(StageIndex))
|
||||
{
|
||||
@@ -654,11 +693,13 @@ void ASeedBedActor::ApplySlotVisuals(FIntVector2 SlotCoordinate, FSeedBedSeedSlo
|
||||
|
||||
Slot.PlantSprite->SetRelativeScale3D(PlantScale);
|
||||
Slot.PlantSprite->SetRelativeLocation(PlantOffset);
|
||||
Slot.PlantSprite->UpdateRelativeLocation(FVector(PlantOffset.X, PlantOffset.Y, 0.f));
|
||||
|
||||
if (SeedData->SeedStages[StageIndex].Sprite.IsValid())
|
||||
{
|
||||
Slot.PlantSprite->SetSprite(SeedData->SeedStages[StageIndex].Sprite.Get());
|
||||
Slot.PlantSprite->SetVisibility(true);
|
||||
Slot.PlantSprite->DecalComponent->SetVisibility(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -673,8 +714,36 @@ void ASeedBedActor::ApplySlotVisuals(FIntVector2 SlotCoordinate, FSeedBedSeedSlo
|
||||
Slot->PlantSprite->SetSprite(Sprite);
|
||||
}));
|
||||
}
|
||||
|
||||
if (Slot.SlotData.bBloomed && !Slot.NiagaraComponent->IsActive())
|
||||
{
|
||||
Slot.NiagaraComponent->SetAsset(nullptr);
|
||||
Slot.NiagaraComponent->Activate(false);
|
||||
|
||||
if (PlantBloomedVfx.IsValid())
|
||||
{
|
||||
Slot.NiagaraComponent->SetAsset(PlantBloomedVfx.Get());
|
||||
Slot.NiagaraComponent->Activate(true);
|
||||
Slot.NiagaraComponent->SetVisibility(true);
|
||||
}
|
||||
void ASeedBedActor::RefreshSlotVisual(FIntVector2 SlotCoordinate)
|
||||
else
|
||||
{
|
||||
PlantBloomedVfx.LoadAsync(FLoadSoftObjectPathAsyncDelegate::CreateWeakLambda(this, [this, SlotCoordinate](const FSoftObjectPath& Path, UObject* EffectObj)
|
||||
{
|
||||
FSeedBedSeedSlot* Slot = SeedBedSeedSlotsMap.Find(SlotCoordinate);
|
||||
if (!Slot || !IsValid(Slot->NiagaraComponent)) return;
|
||||
|
||||
UNiagaraSystem* NiagaraSystem = Cast<UNiagaraSystem>(EffectObj);
|
||||
if (!IsValid(NiagaraSystem)) return;
|
||||
|
||||
Slot->NiagaraComponent->SetAsset(NiagaraSystem);
|
||||
Slot->NiagaraComponent->ResetSystem();
|
||||
Slot->NiagaraComponent->SetVisibility(true);
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
void ASeedBedActor::RefreshSlotVisual(const FIntVector2& SlotCoordinate)
|
||||
{
|
||||
FSeedBedSeedSlot* Slot = SeedBedSeedSlotsMap.Find(SlotCoordinate);
|
||||
if (!Slot)
|
||||
@@ -698,7 +767,7 @@ void ASeedBedActor::RefreshAllSlotVisuals()
|
||||
bool ASeedBedActor::IsPlantableSeedData(const UItemDataAsset* SeedData)
|
||||
{
|
||||
// Only seeds of plants make it into a bed, the meshes are optional and fall back to DefaultPlantMesh
|
||||
return IsValid(SeedData) && SeedData->IsSeed;
|
||||
return IsValid(SeedData) && SeedData->ItemCategory == Category::Seed;
|
||||
}
|
||||
|
||||
void ASeedBedActor::HighlightSlot(FIntVector2 SlotCoordinate)
|
||||
@@ -816,7 +885,7 @@ int32 ASeedBedActor::ResolveGrowthStageIndex(const FSeedBedSeedSlot& Slot) const
|
||||
}
|
||||
|
||||
// Stages are set up per day while the age of a plant counts hours, so the last day that was reached wins
|
||||
int32 StageIndex = 0;
|
||||
int32 StageIndex = INDEX_NONE;
|
||||
|
||||
for (int32 Index = 0; Index < SeedData->SeedStages.Num(); ++Index)
|
||||
{
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
#include "ProjectEleri/System/TimeOfDayStruct.h"
|
||||
#include "SeedBedActor.generated.h"
|
||||
|
||||
class UNiagaraSystem;
|
||||
class UNiagaraComponent;
|
||||
class UEleriPaperSpriteComponent;
|
||||
class UPaperSpriteComponent;
|
||||
class ATimeOfDayManager;
|
||||
class UDecalComponent;
|
||||
@@ -81,7 +84,10 @@ struct FSeedBedSeedSlot
|
||||
UMaterialInstanceDynamic* SeedBedDynamicMat = nullptr;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
|
||||
UPaperSpriteComponent* PlantSprite;
|
||||
UEleriPaperSpriteComponent* PlantSprite = nullptr;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
|
||||
UNiagaraComponent* NiagaraComponent = nullptr;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
@@ -144,6 +150,9 @@ public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Seed Bed|Setup")
|
||||
FIntVector2 GridSize = FIntVector2(3, 3);
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Seed Bed|Setup")
|
||||
TSoftObjectPtr<UNiagaraSystem> PlantBloomedVfx;
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// HIGHLIGHT DECAL
|
||||
//------------------------------------------------------------------------------------------------
|
||||
@@ -249,7 +258,7 @@ public:
|
||||
|
||||
/** Re-applies mesh, material and decal of a single slot */
|
||||
UFUNCTION(BlueprintCallable, Category = "Seed Bed|Visuals")
|
||||
void RefreshSlotVisual(FIntVector2 SlotCoordinate);
|
||||
void RefreshSlotVisual(const FIntVector2& SlotCoordinate);
|
||||
|
||||
/** Re-applies mesh, material and decal of every slot of the bed */
|
||||
UFUNCTION(BlueprintCallable, Category = "Seed Bed|Visuals")
|
||||
@@ -287,7 +296,7 @@ protected:
|
||||
void BindToTimeOfDay();
|
||||
|
||||
/** Applies one in game hour of growth, moisture handling and death checks to a single slot */
|
||||
void ApplyHourPassedToSlot(FSeedBedSeedSlot& Slot, const FTimeOfDayData& Now);
|
||||
void ApplyHourPassedToSlot(FSeedBedSeedSlot& Slot, const FTimeOfDayData& Now, const FIntVector2& SlotCoordinate);
|
||||
|
||||
/** Catches the plants up on the in game time that passed while the bed was not in the world */
|
||||
void ApplyOfflineProgression();
|
||||
|
||||
@@ -51,6 +51,9 @@ public:
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "Ability System|Settings")
|
||||
TSoftObjectPtr<UDataTable> GlobalSettingsDataSheet;
|
||||
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "Materials")
|
||||
TSoftObjectPtr<UMaterialInterface> SpriteShadowMaterial;
|
||||
|
||||
public:
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Eleri Game Settingss")
|
||||
|
||||
Reference in New Issue
Block a user