#Basically, if you're doing it in BP,
1 messages ยท Page 1 of 1 (latest)
Ok but we are not talking about loading the asset for usage later, but setting it on startup right? I zoomed out a bit and I am ofc loading it async on usage.
What I don't get is how to know which mesh to set to the data asset on startup, since what I have already set in the DataAsset (UI) is a nullptr. And that's the only reference I have to load it ๐ค
Oh, well that's different
So the validity check passes, you're absolutely sure the soft pointer is pointing to something, but once it's finished loading, the loaded object ptr is null?
The only reason I have to believe that it is ever set is this image I showed earlier. But then when I interact with it, it's None
The last row in the data asset is me setting the mesh
Try putting a breakpoint on the branch, see what the IsValidSoftObjectReference returns
Also check what the return value of the GetStaticMesh func is
It's really not there ๐
TSoftObjectPtr<UStaticMesh> UItemAsset::GetStaticMesh_Implementation() const
{
if (StaticMesh.IsValid())
{
UE_LOG(LogTemp, Log, TEXT("Static Mesh from ItemAsset is valid: %s"), *StaticMesh->GetName());
return StaticMesh;
}
UE_LOG(LogTemp, Warning, TEXT("Static Mesh from ItemAsset is not valid"));
return nullptr;
}
I also see that this is logging that the SoftObjectPtr is invalid
Are you sure your EquipmentAssetCpp is implementing the interface?
And if it is, is the function GetStaticMesh defined?
Since it inherits from ItemAsset I got the notion it was not needed, it looks like this;
.h
UCLASS(Blueprintable, BlueprintType)
class DO_API UEquipmentAssetCpp : public UItemAsset
{
GENERATED_BODY()
public:
virtual TSoftObjectPtr<USkeletalMesh> GetSkeletalMesh_Implementation() const override;
virtual TSoftObjectPtr<UStaticMesh> GetStaticMesh_Implementation() const override;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Equipment")
bool bIsPartOfSet = false;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Equipment")
FName EquipmentSetIdentifier;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Ability")
TSoftClassPtr<UGameplayAbility> UseEquipmentAbilityClass;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Ability")
TSoftClassPtr<UGameplayEffect> EquipEffectClass;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Modifiers")
TArray<FAttributeModifier> Modifiers;
};
.cpp
TSoftObjectPtr<UStaticMesh> UEquipmentAssetCpp::GetStaticMesh_Implementation() const
{
TSoftObjectPtr<UStaticMesh> Mesh = Super::GetStaticMesh_Implementation();
if (Mesh.IsValid())
{
UE_LOG(LogTemp, Log, TEXT("Static Mesh from EquipmentAsset is valid: %s"), *Mesh->GetName());
}
else
{
UE_LOG(LogTemp, Warning, TEXT("Static Mesh from EquipmentAsset is not valid"));
}
return Mesh;
}
I tried it earlier but Rider was complaining, I will try it again if you think that's the issue that EquipmentAssetCpp is not implementing IHasWorldRepresentation as well
Try setting a breakpoint in that function in cpp, see if it gets called
Does the log appear in the output window?
Only the ItemAsset log appears for EquipmentAssetCpp's
"Static Mesh from ItemAsset is not valid" but never "Static Mesh from EquipmentAsset is not valid"
Nope my bad, both are there actually
Thanks alot for trying to help out btw, truly appreciate it
It really feels like it boils down to that the StaticMesh is never stored on the ItemAsset even though I set it.
๐
The last thing to check is what exactly you're casting to EquipmentAssetCpp
I.e. are you getting the same object you're setting the static mesh to
And the Shoulder_Steel_01 has that mesh set?
Correct
OK, one last thing
Put a breakpoint in cpp in the GetStaticMesh_Implementation function
Once it hits that breakpoint, check what the StaticMesh variable is
You can hover over, or you can look in the Autos or Locals window to read the value.
Sorry if I sound a bit condenscending, not sure what your level of expertese is xD
I'm am very very new
But there we have it
It's there...
But it is a nullptr as well
Or well, I read it wrongly. I guess it is a nullptr the other is just the asset path of the shoulders ofc
Wait a sec
Replace IsValid() with IsNull()
TSoftObjectPtr is templatized wrapper of the generic [FSoftObjectPtr](API\Runtime\CoreUObject\UObject...
IsValid() tests if it's pointing to something and that something is loaded. IsNull() tests if it's pointing to something, whether loaded or not.
Ok, updating. Exciting!
Let me know if it works
It passes the check but it's still not there ๐
Damn. I thought it'd work
But hey, one step at a time. So now the check passes, and the log says that the mesh is valid?
Eyy, exactly!
One last thing that is just so obvious that I wanna double check it
Is this correctly defined:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Item)
TSoftObjectPtr<USkeletalMesh> SkeletalMesh;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Item)
TSoftObjectPtr<UStaticMesh> StaticMesh;
Yes, but a small advice - never use BlueprintReadWrite on data assets.
If you change it in one place, it changes everywhere.
But anyway, looking back at the BP graph, the same mistake is repeated there. You're checking if the soft object pointer is valid.
For testing purposes, I'd just remove the branch and see if anything loads.
The thing is, if I keep it as IsNull() in the GetStaticMesh method UE crashes due to the exception above
So not sure I can test it, but maybe you are on to something with BlueprintReadWrite - maybe something updates those properties to be nullptrs. Not sure how but I will test without it
That would be good
Take a look at the call stack, see what got called that crashed it
Ah, of course, must be because you're directly dereferencing the mesh
With *Mesh
Not sure if that operator is overloaded in TSoftObjectPtr
Even if it is, you're still trying to access an asset that hasn't been loaded yet
You could use Mesh.GetAssetName()
Removed it for the time being, trying again in a min
Ok, so I still have some blueprint classes that are implementing the ItemAsset, for those it works. E.g. if I drop an item into the world, I can see the default mesh I have set in Blueprints for "PickableItems".
OK, that's a good start
Don't forget to remove the validity check from the blueprint
Not sure if blueprints have a IsNull version. They should
But I haven't used soft object ptrs in blueprints for a while now xD
Nope, there is nothing for that. I'll just remove it and check after loading the asset if I found something. At least we can eliminate if the pointer is actually there
You could restructure your code a bit so that you don't have to double check in the code and in the blueprint, but let's first make sure that it actually works now.
Yeah, I had this in blueprints before but I got tired of it and I'm slowly moving everything to cpp
Or when I started with GAS, I started defining a lot of other stuff in cpp and just realised how inefficient it is to work in blueprints. A straight and easy thought is easily represented, but any type of complex logic becomes unmaintainable almost instantly ๐
Sad to say, I am never getting to the postive outcome of the branch:
Yeah, as you work, you'll see yourself using cpp a lot more
I barely do anything in blueprints anymore
But damn, this one is a bitch
What does the log say?
Oh right, you've removed it
I removed the templating
But the log is weird
LogTemp: Warning: Static Mesh from ItemAsset is not valid
LogTemp: Static Mesh from EquipmentAsset is valid
LogStreamableManager: Display: RequestAsyncLoad() called with empty or only null assets!
LogTemp: Warning: Static Mesh from ItemAsset is not valid
LogTemp: Static Mesh from EquipmentAsset is valid
LogTemp: Static Mesh from WeaponAsset is valid
LogTemp: Warning: Static Mesh from ItemAsset is not valid
LogTemp: Static Mesh from EquipmentAsset is valid
LogTemp: Static Mesh from WeaponAsset is valid
LogTemp: Warning: Static Mesh from ItemAsset is not valid
LogTemp: Static Mesh from EquipmentAsset is valid
LogStreamableManager: Display: RequestAsyncLoad() called with empty or only null assets!
LogBlueprintUserMessages: [Largee] Server: 100.0:100.0
LogTemp: Warning: Static Mesh from ItemAsset is not valid
LogTemp: Static Mesh from EquipmentAsset is valid
LogStreamableManager: Display: RequestAsyncLoad() called with empty or only null assets!
LogTemp: Warning: Static Mesh from ItemAsset is not valid
LogTemp: Static Mesh from EquipmentAsset is valid
LogStreamableManager: Display: RequestAsyncLoad() called with empty or only null assets!
It's only checking for null now
So ItemAsset says it's not null and returns a nullptr
Which then goes to equipmentcpp that thinks it's valid because it is a nullptr
Could you show me the new version of the get static mesh function, please?
TSoftObjectPtr<UStaticMesh> UEquipmentAssetCpp::GetStaticMesh_Implementation() const
{
TSoftObjectPtr<UStaticMesh> Mesh = Super::GetStaticMesh_Implementation();
if (Mesh.IsNull())
{
UE_LOG(LogTemp, Log, TEXT("Static Mesh from EquipmentAsset is valid"));
}
else
{
UE_LOG(LogTemp, Warning, TEXT("Static Mesh from EquipmentAsset is not valid"));
}
return Mesh;
}
TSoftObjectPtr<UStaticMesh> UItemAsset::GetStaticMesh_Implementation() const
{
if (StaticMesh.IsNull())
{
UE_LOG(LogTemp, Log, TEXT("Static Mesh from ItemAsset is valid"));
return StaticMesh;
}
UE_LOG(LogTemp, Warning, TEXT("Static Mesh from ItemAsset is not valid"));
return nullptr;
}
So StaticMesh is not null ๐ค
It should read If(!StaticMesh.IsNull())
You forgot to negate the bool
You're printing that it's valid when it's not valid
But that still doesn't explain why it's null to begin with.
Actually, looking back at the log
The parent function doesn't return null
Because it says LogTemp: Warning: Static Mesh from ItemAsset is not valid, and the condition was reversed
It worked..
The overridden function returns null, which is odd
Gdamn, I don't know how to thank you. This would have put me in another week of hiatus otherwise ๐
{
if (StaticMesh.IsNull()) <-- mesh was NOT null, so this returned false.
{
UE_LOG(LogTemp, Log, TEXT("Static Mesh from ItemAsset is valid"));
return StaticMesh;
}
UE_LOG(LogTemp, Warning, TEXT("Static Mesh from ItemAsset is not valid"));
return nullptr; <--- returned a nullptr as a result
}```
And then the overridden function got nullptr, but given that the condition was reversed, it printed that the mesh is valid.