• 关于UE4对象静态/动态的销毁问题整理(AddToRoot、TWeakObjectPtr)


    1.非UObject对象

    即非UObject常规C++对象,创建销毁不赘述。但可以用智能指针;从而不用关心销毁逻辑:

    TSharedPtr<ClassA> MyObj = MakeShareable(new ClassA());

    智能指针转裸指针:

    ClassA* MyObjPtr = MyObj.Get();

    智能指针情况下,当别的类引用该对象,并要知道引用的字段是否=nullptr,则需使用弱指针(TWeakPtr):

    class ClassB
    {
    public:
        TWeakPtr<ClassA> ClassAReference;
    };
    ClassB ClassBObj;
    ClassBObj.ClassAReference = MyObj;
    //...
    if (ClassBObj.ClassAReference.IsValid())
    {
        //...
    }

    2.场景引用的UObject对象

    第二种是链接在场景中的UObject对象,UObject本身不会产生释放销毁问题,因为走的是UE自己的垃圾回收。

    但有时会无法获取当前对象是否已销毁的状态。

    例如:


    UCLASS()
    class AMyClass : public ACharacter { GENERATED_BODY() public: class UActorComponent* TestUObj; //...

    TestUObj没有加UPROPERTY,此时无法判断是否销毁:

    TestUObj->DestroyComponent();//销毁测试
    
    if (TestUObj)
        UE_LOG(LogTemp, Log, TEXT("Not Destroy!"));//最后一定进到这里
    else
        UE_LOG(LogTemp, Log, TEXT("Destroyed!"));

    回到刚刚的AMyClass,加上UPROPERTY宏,即可解决。UE会跟踪其生命周期:

    UPROPERTY(VisibleAnywhere)//加上
    class UActorComponent* TestUObj;

    但如果不想用UPROPERTY又需要知道当前对象是否已销毁,则可以用弱对象指针TWeakObjectPtr

    (TWeakObjectPtr和TWeakPtr弱指针的区别是,TWeakObjectPtr针对UObject对象,TWeakPtr针对常规C++对象):

    TWeakObjectPtr<UActorComponent> ptr = MakeWeakObjectPtr(TestUObj);//弱对象指针
    TestUObj->DestroyComponent();//销毁
    
    if (ptr.IsValid())
    {
        UE_LOG(LogTemp, Log, TEXT("Not Destroy!"));
    }
    else
    {
        UE_LOG(LogTemp, Log, TEXT("Destroyed!"));//正常了
    }

    3.动态创建的UObject对象

    动态创建的对象主要问题是,每隔一段时间对象就会自动被垃圾回收机制销毁,该问题通常会导致UE崩溃,并弹窗报错Pure Virtual Function。

    这是因为动态创建的对象还要调用一下AddToRoot,才可避免被自动回收:

    TestUObj = NewObject<UActorComponent>(this, TEXT("Dynamic Obj1"));
    TestUObj->AddToRoot();

    在释放时,还需手动调用RemoveFromRoot,否则UE会断言报错:

    TestUObj->RemoveFromRoot();

    4.UInterface接口对象的释放

    除非是引用关系,UInterface也要留意销毁,而销毁时可以通过_getUObject拿到UObject进行操作。下例用其去调用RemoveFromRoot,

    保证与AddToRoot的成对调用:

    IMyInterface* myInterface;
    myInterface->_getUObject()->RemoveFromRoot();
  • 相关阅读:
    双网卡主机无法管理的故障
    hosts文件导致无法访问网站
    获取webshell的十种方法
    XSS跨站攻击
    Ubuntu 使用中的问题总结
    ubuntu linux 13.04更新
    mysql root密码重置
    防火墙工作模式简介
    SE 2014年4月30日
    SE 2014年4月29日
  • 原文地址:https://www.cnblogs.com/hont/p/16255652.html
Copyright © 2020-2023  润新知