Hey,
I spawn about 200x200 instanced cube’s. Now, when the player clicks one it should change it’s color.
Question 1.) is that even possible that instances have different textures / materials?
Question 2.) If yes, how to I perform line traces?
Currently my line trace gets me a “StaticMeshActor” but when I try to cast it to my class (InstancedCell : public StaticMeshActor), the cast fails.
.h
UCLASS()
class CROCHET_API AInstancedCell : public AStaticMeshActor
{
GENERATED_BODY()
public:
UPROPERTY()
class UMaterialInstance* OrangeMaterial;
UPROPERTY()
UInstancedStaticMeshComponent* InstancedStaticMeshComponent;
UPROPERTY()
UStaticMesh* SMAsset_Cube;
public:
AInstancedCell(const FObjectInitializer& ObjectInitializer);
UFUNCTION(BlueprintCallable, Category = "Cell")
void onClicked();
};
.cpp
AInstancedCell::AInstancedCell(const FObjectInitializer& ObjectInitializer)
{
struct FConstructorStatics
{
ConstructorHelpers::FObjectFinderOptional<UStaticMesh> PlaneMesh;
ConstructorHelpers::FObjectFinderOptional<UMaterialInstance> BlueMaterial;
ConstructorHelpers::FObjectFinderOptional<UMaterialInstance> OrangeMaterial;
FConstructorStatics()
: PlaneMesh(TEXT("/Game/StarterContent/Shapes/Shape_Plane.Shape_Plane"))
, BlueMaterial(TEXT("/Engine/TemplateResources/MI_Template_BaseBlue.MI_Template_BaseBlue"))
, OrangeMaterial(TEXT("/Engine/TemplateResources/MI_Template_BaseOrange.MI_Template_BaseOrange"))
{
}
};
static FConstructorStatics ConstructorStatics;
//Mesh
static ConstructorHelpers::FObjectFinder<UStaticMesh> StaticMeshOb_torus(TEXT("StaticMesh'/Engine/EngineMeshes/Cube.Cube'"));
SMAsset_Cube = StaticMeshOb_torus.Object;
//create new object
InstancedStaticMeshComponent = ObjectInitializer.CreateDefaultSubobject < UInstancedStaticMeshComponent >(this, TEXT("InstancedStaticMeshComponentCOMP"));
InstancedStaticMeshComponent->AttachTo(RootComponent);
//Not Made some reason?
if (!InstancedStaticMeshComponent) return;
//~~~~~~~~~~~~~~~~~~~~~~~~
//Set to Asset
InstancedStaticMeshComponent->SetStaticMesh(SMAsset_Cube);
InstancedStaticMeshComponent->bOwnerNoSee = false;
InstancedStaticMeshComponent->bCastDynamicShadow = false;
InstancedStaticMeshComponent->CastShadow = false;
InstancedStaticMeshComponent->BodyInstance.SetObjectType(ECC_WorldDynamic);
//Visibility
InstancedStaticMeshComponent->SetHiddenInGame(false);
//Mobility
InstancedStaticMeshComponent->SetMobility(EComponentMobility::Movable);
//Collision
InstancedStaticMeshComponent->BodyInstance.SetCollisionEnabled(ECollisionEnabled::QueryOnly);
InstancedStaticMeshComponent->BodyInstance.SetObjectType(ECC_WorldDynamic);
InstancedStaticMeshComponent->BodyInstance.SetResponseToAllChannels(ECR_Ignore);
InstancedStaticMeshComponent->BodyInstance.SetResponseToChannel(ECC_WorldStatic, ECR_Block);
InstancedStaticMeshComponent->BodyInstance.SetResponseToChannel(ECC_WorldDynamic, ECR_Block);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (!StaticMeshComponent) return;
//Mobility
StaticMeshComponent->SetMobility(EComponentMobility::Movable);
//Collision
GetStaticMeshComponent()->BodyInstance.SetCollisionEnabled(ECollisionEnabled::Type::QueryAndPhysics);
GetStaticMeshComponent()->BodyInstance.SetObjectType(ECC_WorldDynamic);
GetStaticMeshComponent()->BodyInstance.SetResponseToChannel(ECC_WorldStatic, ECR_Block);
GetStaticMeshComponent()->BodyInstance.SetResponseToChannel(ECC_WorldDynamic, ECR_Block);
GetStaticMeshComponent()->BodyInstance.SetResponseToAllChannels(ECR_MAX);
OrangeMaterial = ConstructorStatics.OrangeMaterial.Get();
}
void AInstancedCell::onClicked(){
InstancedStaticMeshComponent->SetMaterial(0, OrangeMaterial);
}
Spawning
ACrochetBlockGrid::ACrochetBlockGrid()
{
// Create dummy root scene component
DummyRoot = CreateDefaultSubobject<USceneComponent>(TEXT("Dummy0"));
RootComponent = DummyRoot;
// Create static mesh component
ScoreText = CreateDefaultSubobject<UTextRenderComponent>(TEXT("ScoreText0"));
ScoreText->SetRelativeLocation(FVector(200.f,0.f,0.f));
ScoreText->SetRelativeRotation(FRotator(90.f,0.f,0.f));
ScoreText->SetText(FText::Format(LOCTEXT("ScoreFmt", "Score: {0}"), FText::AsNumber(0)));
ScoreText->AttachTo(DummyRoot);
static ConstructorHelpers::FObjectFinder<UStaticMesh> staticMesh(TEXT("StaticMesh'/Game/StarterContent/Shapes/Shape_Plane.Shape_Plane'"));
mesh = staticMesh.Object;
// Set defaults
Size = 300;
BlockSpacing = 110.f;
}
void ACrochetBlockGrid::BeginPlay()
{
Super::BeginPlay();
FActorSpawnParameters SpawnInfo;
//SET NO COLLISION FAIL TO TRUE
SpawnInfo.bNoCollisionFail = true;
SpawnInfo.Owner = this;
//meshComp->SetMaterial(0, Material.Object);
AInstancedCell* NewVertex =
GetWorld()->SpawnActor<AInstancedCell>(
AInstancedCell::StaticClass(),
FVector(0,0,0),
FRotator::ZeroRotator,
SpawnInfo
);
// if (!NewVertex) return NULL;
//if (!NewVertex->InstancedStaticMeshComponent) return NULL;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Mesh
NewVertex->InstancedStaticMeshComponent->SetStaticMesh(mesh);
//Add Core Instance
FTransform newT = NewVertex->GetTransform();
newT.SetLocation(FVector(0, 0, 0));
NewVertex->InstancedStaticMeshComponent->AddInstance(newT);
//Scale
//NewVertex->SetActorRelativeScale3D(CurrentVerticiesScale);
// Number of blocks
const int32 NumBlocks = Size * Size;
// Loop to spawn each block
for(int32 BlockIndex=0; BlockIndex<NumBlocks; BlockIndex++)
{
const float XOffset = (BlockIndex/Size) * BlockSpacing; // Divide by dimension
const float YOffset = (BlockIndex%Size) * BlockSpacing; // Modulo gives remainder
// Make postion vector, offset from Grid location
const FVector BlockLocation = FVector(XOffset, YOffset, 0.f) + GetActorLocation();
// Spawn a block
FTransform newT = NewVertex->GetTransform();
newT.SetLocation(BlockLocation);
NewVertex->InstancedStaticMeshComponent->AddInstance(newT);
//AInstancedCell* NewBlock = GetWorld()->SpawnActor<AInstancedCell>(BlockLocation, FRotator(0, 0, 0));
}
}