So my problem is I get an access violation when I want to change a parameter of my material instance when clicking on the mesh. I’ve tried different things for 2hrs now and can’t seem to find what I’m doing wrong. I’m working within a class derived from UStaticMeshComponent.
This is my setup:
Constructor:
auto materialAsset = ConstructorHelpers::FObjectFinder<UMaterial>(TEXT("Material'/Game/Materials/M_Editor_Node.M_Editor_Node'"));
if (materialAsset.Object != nullptr)
{
UMaterialInterface * mInterface = Cast<UMaterialInterface>(materialAsset.Object);
if (mInterface != nullptr)
{
SetMaterial(0, mInterface);
}
else
{
Logging::Log("Couldn't cast material to interface");
}
}
else
{
Logging::Log("Could not find Asset at path '/Game/Materials/MI_Editor_Node.MI_Editor_Node' in CellEditor_NodeComponent.Constructor");
}
These components are all created on runtime and need to get some additional values so I got this PostConstructor:
materialDynamic = UMaterialInstanceDynamic::Create(this->GetMaterial(0), this);
/* Some more stuff... */
And finally in my function that registers the click:
Okay, the only real difference I can see is that you set the param inside the actor while I do it inside the component. Could this have any effect on my problem?
Okay, I checked line 182 and it’s actually not the line where I set the param but the closing bracket of the entire function.
It works when I delete the line where I set the param, tho.
When you delete the line, does it work as expected, as in the material changes, or does it just not crash? If it just doesn’t crash you’ve found the offending line of code, and now we can work toward fixing it
I’ve looked a bit into “EXCEPTION_ACCESS_VIOLATION reading address 0xffffffff”. In Unreal it tends to happen when something is not (yet) set or initialized. So this might be an issue of you not calling Super methods on your overridden methods(for example: in your class derived from UStaticMeshComponent). It could be that you’re trying to change parameters of a material that is not yet initialized, used etc. Maybe you’re overriding the materials in blueprints or something like that, and the material you’re trying to change in C++ does not have the parameter.
Also, since I don’t have the whole code, are you saving a reference to your material to materialDynamic variable? You can access it in a UStaticMesh derived class via GetMaterial
If I delete the line setting the param, it doesn’t crash but then nothing happens, so that’s definitely no solution.
Okay, so something’s not initialized. That’s what I wanted to catch with the if(materialDynamic != nullptr).
I’m loading the material via the FObjectFinder and setting it via this->SetMaterial(); This works since the material actually is on my mesh. So the material has to be initialized.
Maybe when creating a dynamic instance.
materialDynamic is a attribute of my component class.
I tried something different with the constructor. Now it looks like this but I still get the same result:
auto materialAsset = ConstructorHelpers::FObjectFinder<UMaterialInstance>(TEXT("MaterialInstace'/Game/Materials/MI_Editor_Node.MI_Editor_Node'"));
if (materialAsset.Object != nullptr)
{
UMaterialInstance * mInstance = Cast<UMaterialInstance>(materialAsset.Object);
if (mInstance != nullptr)
{
materialDynamic = UMaterialInstanceDynamic::Create(mInstance, this, FName("Material"));
//materialDynamic = CreateAndSetMaterialInstanceDynamicFromMaterial(0, GetMaterial(0));
SetMaterial(0, materialDynamic);
}
else
{
Logging::Log("Couldn't cast material to instance");
}
}
else
{
Logging::Log("Could not find Asset at path '/Game/Materials/MI_Editor_Node.MI_Editor_Node' in CellEditor_NodeComponent.Constructor");
}
Maybe this helps a bit:
All the handling for hover and so on is in the staticMeshComponent beause I want to handle all the components individually.
The base class is invisible and just handles the logic. It has a attribute baseNode. It is of the class node.
Each node can have [0 - 4] child nodes.
All the code from the question up there is inside the node class.
Would it help to give you all of the code to look at and maybe test?
I have been struggling with the same odd error starting to pop up on me. Two things.
I use:
WaterMaterial = UMaterialInstanceDynamic::Create(SurfaceMaterial, NULL);
I read that the use of this vs NULL can cause unexpected results - not sure this is an issue, but I read it so worth a try.
I added a second “Create” statement just above my SetScalarParam statement and the crash went away. Which leads me to a sequencing of functions. I think your code is calling the SetScalarParam too soon, my test of adding a new create above it is not the fix, but it does say that in my case. If the object exists then the line doesn’t crash.