#Basically, if you're doing it in BP,

1 messages ยท Page 1 of 1 (latest)

slow glade
#

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 ๐Ÿค”

glossy iron
#

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?

slow glade
#

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

glossy iron
#

Try putting a breakpoint on the branch, see what the IsValidSoftObjectReference returns

#

Also check what the return value of the GetStaticMesh func is

slow glade
#

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

glossy iron
#

Are you sure your EquipmentAssetCpp is implementing the interface?

#

And if it is, is the function GetStaticMesh defined?

slow glade
#

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

glossy iron
#

Try setting a breakpoint in that function in cpp, see if it gets called

#

Does the log appear in the output window?

slow glade
#

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.

glossy iron
#

No problem

#

Hmm, but I'm starting to run out of ideas xD

slow glade
#

๐Ÿ˜„

glossy iron
#

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

slow glade
#

It is an EquipmentAssetCpp in this case

glossy iron
#

And the Shoulder_Steel_01 has that mesh set?

slow glade
#

Correct

glossy iron
#

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

slow glade
#

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

glossy iron
#

Wait a sec

#

Replace IsValid() with IsNull()

#

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.

slow glade
#

Ok, updating. Exciting!

glossy iron
#

Let me know if it works

slow glade
#

It passes the check but it's still not there ๐Ÿ˜„

glossy iron
#

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?

slow glade
#

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;
glossy iron
#

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.

slow glade
#

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

glossy iron
#

Oh

#

Hmmm

#

But when exactly does it crash? What does the call stack say?

slow glade
#

My last image above

#

I can crash it again and get some more info

glossy iron
#

That would be good

#

Take a look at the call stack, see what got called that crashed it

slow glade
#

It's essentially the log that crashes it

#

I will remove it

glossy iron
#

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()

slow glade
#

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".

glossy iron
#

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

slow glade
#

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

glossy iron
#

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.

slow glade
#

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:

glossy iron
#

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

slow glade
#

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

glossy iron
#

Could you show me the new version of the get static mesh function, please?

slow glade
#
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 ๐Ÿค”

glossy iron
#

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

slow glade
#

It worked..

glossy iron
#

The overridden function returns null, which is odd

slow glade
#

IT WORKED

#

Hahahaha

glossy iron
#

Aaah

#

I see now

slow glade
#

Gdamn, I don't know how to thank you. This would have put me in another week of hiatus otherwise ๐Ÿ˜„

glossy iron
#
{
    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.

slow glade
#

Yeah, that one I could potentially have caught but the IsValid vs. IsNull I had no clue about and I don't think I would've stumbled over it for quite some time

#

Really really really big thanks!

glossy iron
#

No problem ๐Ÿ™‚

#

Going to bed now since it's past midnight, but feel free to ask stuff from time to time. I get bored at work xD