【UnLua】ModuleLocator改造-创新互联

【UnLua】Module Locator 改造

看起来简单的东西,UnLua 做的不是很完备,实际项目使用时藏了一些坑,之前没怎么上心,断断续续改,总还是有问题 ,今天彻底解决这个问题

创新互联自2013年创立以来,是专业互联网技术服务公司,拥有项目成都网站设计、成都网站建设网站策划,项目实施与项目整合能力。我们以让每一个梦想脱颖而出为使命,1280元栖霞做网站,已为上家服务,为栖霞各地企业和个人服务,联系电话:13518219792Module Locator 是什么

Lua 接入引擎后一般需要 C++ 重写 require

  • 比如调用引擎的资源管理器去加载 Lua 脚本文件(可以加密,压缩)
  • 比如定制文件路径 resolve 规则(可以 fallback 查找)

UnLua 提供了一个基类ULuaModuleLocator,有Locate接口返回 Lua 路径

UCLASS()
class UNLUA_API ULuaModuleLocator : public UObject
{GENERATED_BODY()
public:
	// 定位 Object 对应的 Lua 文件路径
    virtual FString Locate(const UObject* Object);
};

默认实现长这样,返回UObject->Class->CDO->GetModuleName(),即一个 Object 的 UClass 实现了 UnLuaInterface,就绑定了Lua,运行时会去加载GetModuleName返回的 Lua 文件路径

FString ULuaModuleLocator::Locate(const UObject* Object)
{const UObject* CDO;
    if (Object->HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject))
    {CDO = Object;
    }
    else
    {const auto Class = Cast(Object);
        CDO = Class ? Class->GetDefaultObject() : Object->GetClass()->GetDefaultObject();
    }

    if (CDO->HasAnyFlags(RF_NeedInitialization))
    {// CDO还没有初始化完成
        return "";
    }

    if (!CDO->GetClass()->ImplementsInterface(UUnLuaInterface::StaticClass()))
    {return "";
    }

    return IUnLuaInterface::Execute_GetModuleName(CDO);
}

LyraWithUnLua Demo 里提供了一个实现ULyraLuaModuleLocator,核心是蓝图类使用蓝图资源路径,自动生成 Lua 路径

// 2. if this is blueprint, fallback to generate name by asset path
//	  NOTE will try to remove prefix W_, UI_, GA_
if (ModuleName.IsEmpty() && !Class->IsNative()  && !CheckSuperModuleName())
{// 蓝图类使用资源路径
	ModuleName = Class->GetPackage()->GetName();
	ModuleName = ModuleName.Replace(TEXT("/"), TEXT("."));

	TArrayParts;
	ModuleName.ParseIntoArray(Parts, TEXT("."));
	if (Parts.Num() >0)
	{auto& LastPart = Parts[Parts.Num() - 1];
		int32 Index = 0;
		if (LastPart.FindChar('_', Index) && Index< 4)
		{	LastPart.RightChopInline(Index + 1);
		}
		ModuleName = FString::Join(Parts, TEXT("."));
	}
}
问题

ULyraLuaModuleLocator一开始很方便,但是这个接口设计犯了一个错,就是一个接口干了两个接口的活,导致用这个接口怎么也干不好,参考realloc,同时干mallocfree两件事

ULyraLuaModuleLocator的问题在于,蓝图类构造了继承链之后

这里用 C++ 代表 蓝图代码

在基类上绑定 Lua,预期是只有基类绑定了 Lua,但是实际是派生类 也自动绑定了 Lua,运行时会找不到 Lua 文件,然后报错

class BP_A : UnLuaInterface {GetModuleName =>"BP_A"; }
class BP_B : BP_A {GetModuleName =>""; }  // 派生,没绑Lua
class BP_C_DataOnly : BP_B {GetModuleName =>""; }  // 派生,没绑Lua
class BP_A : UnLuaInterface {GetModuleName =>"BP_A"; 
	virtual
}
class BP_B : BP_A {GetModuleName =>""; }  // 派生,没绑Lua
class BP_C_DataOnly : BP_B {GetModuleName =>""; }  // 派生,没绑Lua
解决

分两个接口来做

  • 额外加一个按钮自动填充 GetModuleName 路径,使用ULyraLuaModuleLocator,只有这个按钮会走这里
  • 运行时,编辑器跑ULuaModuleLocator,简单,稳定,快速
继承相关的问题

【UnLua】Super 继承和 override_zoloypzuo的博客-博客

这篇文章中,我们仔细讨论了继承的情况,建议阅读,两篇文章有关联

小结

主要是编程上的注意

  • 分离 Editor 和 Runtime 行为
  • 一个接口只做一件事,不要同时负责写入+读取
  • Runtime 行为保持简单,确定性,不要有潜规则,难以调试,容易隐藏问题

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


网站名称:【UnLua】ModuleLocator改造-创新互联
网页网址:http://ybzwz.com/article/cdsiso.html