当前位置: 首页 > news >正文

输出UE当前所有UObject的基础信息

目标

之前尝试制作过一个观察UObject的工具,但是那个工具的封装有些冗余了。。

本篇将写个函数直接输出所有UObject的所有基础信息。

Uobject基础信息

Uobject的继承关系如下:

UObjectBase
UObjectBaseUtility
UObject

UObject类和UObjectBaseUtility类都没有定义新的字段。基础信息都在UObjectBase中定义,共有五个:

	/** Flags used to track and report various object states. This needs to be 8 byte aligned on 32-bit
	    platforms to reduce memory waste */
	EObjectFlags					ObjectFlags;

	/** Index into GObjectArray...very private. */
	int32							InternalIndex;

	/** Class the object belongs to. */
	UClass*							ClassPrivate;

	/** Name of this object */
	FName							NamePrivate;

	/** Object this object resides in. */
	UObject*						OuterPrivate;

也有对应public函数可以访问:

	/** 
	 * Returns the unique ID of the object...these are reused so it is only unique while the object is alive.
	 * Useful as a tag.
	**/
	FORCEINLINE uint32 GetUniqueID() const
	{
		return (uint32)InternalIndex;
	}

	/** Returns the UClass that defines the fields of this object */
	FORCEINLINE UClass* GetClass() const
	{
		return ClassPrivate;
	}
	
	/** Returns the UObject this object resides in */
	FORCEINLINE UObject* GetOuter() const
	{
		return OuterPrivate;
	}

	/** Returns the logical name of this object */
	FORCEINLINE FName GetFName() const
	{
		return NamePrivate;
	}
	
	/**
	 * Retrieve the object flags directly
	 *
	 * @return Flags for this object
	 **/
	FORCEINLINE EObjectFlags GetFlags() const
	{
		checkfSlow((ObjectFlags & ~RF_AllFlags) == 0, TEXT("%s flagged as RF_AllFlags"), *GetFName().ToString());
		return ObjectFlags;
	}

这五个信息也是本篇想输出出来的内容

写一个函数输出UE当前所有UObject的基础信息

对于这五个信息:

  • InternalIndex 很直白,就输出编号就行了。
  • NamePrivate 是这个Object的名字,也是直接输出。
  • ClassPrivate 说明了这个Object的类,而 “类”——UClass,也是一种Object,所以也可以直接输出它的名字。
  • OuterPrivate 是这个Object的Outer。需要注意的是,Outer之外可能还有Outer,所以需要递归的方式来输出。
  • ObjectFlags 是这个Object的Flag。它的每一位都是一个标志,可以使用&符号来查询是否存在这个标志。(由于它所属的枚举类并非是UENUM,没有反射信息,所以我只能逐个手写出每个标志对应的字符串了)

最后完整的函数如下:

DEFINE_LOG_CATEGORY_STATIC(LogYKS, Log, All);

FString RecursiveGetOuterText(UObject* Object, FString Result)
{
	if (!Object->GetOuter())
		return Result;
	else
	{
		Result += "->(" + Object->GetOuter()->GetFName().ToString() + ")";
		return RecursiveGetOuterText(Object->GetOuter(), Result);
	}
}

FString GetFlagText(EObjectFlags Flag)
{
	FString Result;

	if (Flag & RF_NoFlags)
		Result += "+RF_NoFlags";

	if (Flag & RF_Public)
		Result += "+RF_Public";

	if (Flag & RF_Standalone)
		Result += "+RF_Standalone";

	if (Flag & RF_MarkAsNative)
		Result += "+RF_MarkAsNative";

	if (Flag & RF_Transactional)
		Result += "+RF_Transactional";

	if (Flag & RF_ClassDefaultObject)
		Result += "+RF_ClassDefaultObject";

	if (Flag & RF_ArchetypeObject)
		Result += "+RF_ArchetypeObject";

	if (Flag & RF_Transient)
		Result += "+RF_Transient";

	if (Flag & RF_MarkAsRootSet)
		Result += "+RF_MarkAsRootSet";

	if (Flag & RF_TagGarbageTemp)
		Result += "+RF_TagGarbageTemp";

	if (Flag & RF_NeedInitialization)
		Result += "+RF_NeedInitialization";

	if (Flag & RF_NeedLoad)
		Result += "+RF_NeedLoad";

	if (Flag & RF_KeepForCooker)
		Result += "+RF_KeepForCooker";

	if (Flag & RF_NeedPostLoad)
		Result += "+RF_NeedPostLoad";

	if (Flag & RF_NeedPostLoadSubobjects)
		Result += "+RF_NeedPostLoadSubobjects";

	if (Flag & RF_NewerVersionExists)
		Result += "+RF_NewerVersionExists";

	if (Flag & RF_BeginDestroyed)
		Result += "+RF_BeginDestroyed";

	if (Flag & RF_FinishDestroyed)
		Result += "+RF_FinishDestroyed";

	if (Flag & RF_BeingRegenerated)
		Result += "+RF_BeingRegenerated";

	if (Flag & RF_DefaultSubObject)
		Result += "+RF_DefaultSubObject";

	if (Flag & RF_WasLoaded)
		Result += "+RF_WasLoaded";

	if (Flag & RF_TextExportTransient)
		Result += "+RF_TextExportTransient";

	if (Flag & RF_LoadCompleted)
		Result += "+RF_LoadCompleted";

	if (Flag & RF_InheritableComponentTemplate)
		Result += "+RF_InheritableComponentTemplate";

	if (Flag & RF_DuplicateTransient)
		Result += "+RF_DuplicateTransient";

	if (Flag & RF_StrongRefOnFrame)
		Result += "+RF_StrongRefOnFrame";

	if (Flag & RF_NonPIEDuplicateTransient)
		Result += "+RF_NonPIEDuplicateTransient";

	if (Flag & RF_Dynamic)
		Result += "+RF_Dynamic";

	if (Flag & RF_WillBeLoaded)
		Result += "+RF_WillBeLoaded";

	if (Flag & RF_HasExternalPackage)
		Result += "+RF_HasExternalPackage";

	return Result;
}

void PrintAllUObjectInfo()
{
	for (int i = 0; i < GUObjectArray.GetObjectArrayNum(); i++)
	{
		FUObjectItem* ObjectElement = GUObjectArray.IndexToObject(i);
		if (ObjectElement->Object)
		{
			UObject* Object = (UObject*)ObjectElement->Object;

			UE_LOG(LogYKS, Warning, TEXT("[%d], <%s>, %s, %s, %s")
				, Object->GetUniqueID()							//InternalIndex
				, *(Object->GetClass()->GetFName().ToString())	//类
				, *(Object->GetFName().ToString())				//名字
				, *RecursiveGetOuterText(Object, "")			//Outer链
				, *GetFlagText(Object->GetFlags())				//具有的Flag
			);
		}
	}
}

结果

在UE中调用上面的PrintAllUObjectInfo()函数后,将会看到信息被输出出来:
在这里插入图片描述


还可以将信息复制出来,保存为.csv文件,由于上面输出时已经加了,,所以可以被识别为表格。(可以顺带将LogYKS: Warning: 替换为空以去掉多余信息)
保存的.csv文件可以使用Excel打开,这样有排版后更容易浏览:
在这里插入图片描述

相关文章:

  • 【MicroPython ESP32】1.8“tft ST7735带中文驱动显示示例
  • QT提取数据库内容,根据不同字段要求显示不同颜色
  • 最简便的工厂模式
  • 【实战项目】高并发内存池(模拟实现mini_tcmalloc)
  • 173.CI/CD(一):gitlab配置,jenkins的安装配置,jenkins实现基础的CI/CD,Sonarqube代码质量检测,Harbor镜像仓库
  • FastAPI 学习之路(二十七)安全校验
  • office32位和64位有什么区别
  • 猿创征文|python求解四位数 青少年编程电子学会python编程等级考试三级真题解析2021年03月
  • 当事人胜诉后,所预交受理费是否应予退还
  • uniapp的拨打电话,下拉和上划
  • 如何确定 RMAN 的多路复用级别
  • Java excel poi 读取已有文件 ,动态插入一列数据
  • Java项目:SSM企业工资管理系统
  • Python基于Django的汽车销售网站
  • 花好月圆时,邀你一起来读诗!
  • 【347天】每日项目总结系列085(2018.01.18)
  • CSS相对定位
  • gops —— Go 程序诊断分析工具
  • iBatis和MyBatis在使用ResultMap对应关系时的区别
  • js面向对象
  • Laravel5.4 Queues队列学习
  • 翻译:Hystrix - How To Use
  • 深入浅出webpack学习(1)--核心概念
  • 微信小程序--------语音识别(前端自己也能玩)
  • 小程序开发中的那些坑
  • - 转 Ext2.0 form使用实例
  • 完善智慧办公建设,小熊U租获京东数千万元A+轮融资 ...
  • ​ArcGIS Pro 如何批量删除字段
  • #stm32驱动外设模块总结w5500模块
  • #调用传感器数据_Flink使用函数之监控传感器温度上升提醒
  • $emit传递多个参数_PPC和MIPS指令集下二进制代码中函数参数个数的识别方法
  • $redis-setphp_redis Set命令,php操作Redis Set函数介绍
  • (AtCoder Beginner Contest 340) -- F - S = 1 -- 题解
  • (C++)栈的链式存储结构(出栈、入栈、判空、遍历、销毁)(数据结构与算法)
  • (cos^2 X)的定积分,求积分 ∫sin^2(x) dx
  • (C语言)输入自定义个数的整数,打印出最大值和最小值
  • (java)关于Thread的挂起和恢复
  • (附源码)spring boot网络空间安全实验教学示范中心网站 毕业设计 111454
  • (附源码)ssm旅游企业财务管理系统 毕业设计 102100
  • (论文阅读23/100)Hierarchical Convolutional Features for Visual Tracking
  • (免费领源码)python+django+mysql线上兼职平台系统83320-计算机毕业设计项目选题推荐
  • (顺序)容器的好伴侣 --- 容器适配器
  • (四)模仿学习-完成后台管理页面查询
  • (详细版)Vary: Scaling up the Vision Vocabulary for Large Vision-Language Models
  • (学习日记)2024.03.25:UCOSIII第二十二节:系统启动流程详解
  • (一)spring cloud微服务分布式云架构 - Spring Cloud简介
  • .Net CoreRabbitMQ消息存储可靠机制
  • .NET 表达式计算:Expression Evaluator
  • .net中生成excel后调整宽度
  • .secret勒索病毒数据恢复|金蝶、用友、管家婆、OA、速达、ERP等软件数据库恢复
  • @synthesize和@dynamic分别有什么作用?
  • @在php中起什么作用?
  • [ABP实战开源项目]---ABP实时服务-通知系统.发布模式
  • [Android] Amazon 的 android 音视频开发文档
  • [Angular] 笔记 18:Angular Router