UE4 绘制Gizmo
Unity的Gizmos可以很方便的在编辑器下进行调试,Unreal中也有一些办法可以达到效果。
本文主要参考:https://zhuanlan.zhihu.com/p/363625037,进行了一些简化。并在Unreal 4.27中实现。
具体流程如下:
- 需要绘制Gizmo的Actor挂载继承UPrimitiveComponent的组件;该组件重写了CreateSceneProxy方法,这个方法里可以拿到PDI绘制
- 然后进行这个组件的编写(继承UPrimitiveComponent实际上也继承了USceneComponent),手动挂载到Actor上就可以绘制Gizmo了
- 再在Actor的构造函数中编写自动挂载该组件的逻辑,方便使用
先来编写绘制Gizmo的组件,这里命名为UMyPrimitiveComponent:
MyPrimitiveComponent.h (MYPROJECT_API注意替换)
//MyPrimitiveComponent.h #pragma once #include "CoreMinimal.h"
#include "Components/PrimitiveComponent.h"
#include "PrimitiveSceneProxy.h"
#include "MyPrimitiveComponent.generated.h" UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent))
class MYPROJECT_API UMyPrimitiveComponent : public UPrimitiveComponent
{
GENERATED_BODY() public:
//绘制逻辑主要在这里
virtual FPrimitiveSceneProxy* CreateSceneProxy() override; //如果要在非选中情况下始终绘制的话,需要有Bounds信息,所以要重写该函数
virtual FBoxSphereBounds CalcBounds(const FTransform& LocalToWorld) const;
};
MyPrimitiveComponent.cpp
//MyPrimitiveComponent.cpp
#include "MyPrimitiveComponent.h" FPrimitiveSceneProxy* UMyPrimitiveComponent::CreateSceneProxy()
{
class FMySceneProxy : public FPrimitiveSceneProxy
{
public: SIZE_T GetTypeHash() const override
{
static size_t UniquePointer;
return reinterpret_cast<size_t>(&UniquePointer);
} FMySceneProxy(const UPrimitiveComponent* InComponent) : FPrimitiveSceneProxy(InComponent)
{
CacheInComponent = InComponent;
bWillEverBeLit = false;
} virtual void GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const override
{
QUICK_SCOPE_CYCLE_COUNTER(STAT_Draw3DAgentSceneProxy_GetDynamicMeshElements); for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
{
if (VisibilityMap & (1 << ViewIndex))
{
const FSceneView* View = Views[ViewIndex];
FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex); //拿到Actor的矩阵绘制,而不是Component自己的
const FMatrix& LocalToWorld = CacheInComponent->GetTypedOuter<AActor>()->GetTransform().ToMatrixWithScale(); //绘制函数可以去看下PrimitiveDrawingUtils.cpp
DrawOrientedWireBox(PDI
, LocalToWorld.TransformPosition(FVector::ZeroVector)
, LocalToWorld.GetScaledAxis(EAxis::X)
, LocalToWorld.GetScaledAxis(EAxis::Y)
, LocalToWorld.GetScaledAxis(EAxis::Z)
, FVector(100.0, 100.0, 100.0)
, FLinearColor(1.0, 0.0, 0.0, 1.0)
, SDPG_World
, 1.0);
}
}
}
virtual FPrimitiveViewRelevance GetViewRelevance(const FSceneView* View) const override
{
/*const bool bVisibleForSelection = IsSelected();
const bool bShowForCollision = View->Family->EngineShowFlags.Collision && IsCollisionEnabled(); FPrimitiveViewRelevance Result;
Result.bDrawRelevance = (IsShown(View) && bVisibleForSelection) || bShowForCollision;
Result.bDynamicRelevance = true;
Result.bShadowRelevance = IsShadowCast(View);
Result.bEditorPrimitiveRelevance = true;
Result.bEditorNoDepthTestPrimitiveRelevance = true; */
//上面这段表示选中绘制Gizmo FPrimitiveViewRelevance Result;
Result.bDrawRelevance = true;
Result.bDynamicRelevance = true;
Result.bShadowRelevance =false;
Result.bEditorPrimitiveRelevance = true;
Result.bEditorNoDepthTestPrimitiveRelevance = true;
//这段表示始终绘制 return Result;
} virtual uint32 GetMemoryFootprint(void) const override { return(sizeof(*this) + GetAllocatedSize()); }
uint32 GetAllocatedSize(void) const { return(FPrimitiveSceneProxy::GetAllocatedSize()); } private:
const UPrimitiveComponent* CacheInComponent;
}; return new FMySceneProxy(this);
} FBoxSphereBounds UMyPrimitiveComponent::CalcBounds(const FTransform& LocalToWorld) const
{
return FBoxSphereBounds(FBox(FVector(-50, -50, -50), FVector(50, 50, 50))).TransformBy(LocalToWorld);
//因为缩放是1,这里填的就是实际尺寸,也可以遍历所有组件取最大Bounds.
}
然后手动再挂载一下组件,就有效果了:

如果需要像Unity那样;直接就有Gizmo,可以在Actor构造函数中编写逻辑自动挂载组件:
AMyTestActor::AMyTestActor()
{
UBBoxActorGizmoComponent* Gizmo = CreateDefaultSubobject<UBBoxActorGizmoComponent>(TEXT("Gizmo"));
if (Gizmo)
{
Gizmo->SetupAttachment(GetRootComponent());
}
}
UE4 绘制Gizmo的更多相关文章
- Unity3D脚本中文系列教程(十七)
http://dong2008hong.blog.163.com/blog/static/469688272014032332976/ ◆ Static function PrefixLabel(to ...
- 从Unity中的Attribute到AOP(八)
本文将讲一下在UnityEditor命名空间下的一些特性. CallBackOrder,这个Attribute是所有带callback index的Attribute的基类,由于官方也没有给出详细的说 ...
- Unreal学习笔记2-绘制简单三角形
目录 1. 概述 2. 详论 2.1. 代码实现 2.2. 解析:Component 2.3. 解析:材质 2.4. 解析:包围盒 2.5. 解析:Section 3. 其他 4. 参考 1. 概述 ...
- UE4 Tutorial - Custom Mesh Component 用于绘制自定义网格的插件CustomMeshComponent
UE4 中用于绘制自定义网格的插件CustomMeshComponent. 转载: UE4 Tutorial - Custom Mesh Component Over the last few w ...
- unity gizmo绘制圆形帮助调试
using UnityEngine; using System.Collections; using System; public class LearnGrazio : MonoBehaviour ...
- UE4射线的碰撞与绘制
http://blog.csdn.net/qq992817263/article/details/51800657 //起点 终点 FHitResult RayGetHitResult(FVector ...
- [UE4][Canvas]用C++代码绘制血条(HealthBar)
转自:http://aigo.iteye.com/blog/2275110 参考自Epic官方项目StrategyGame 血条效果: StrategyHUD.h StrategyHUD.cpp
- 【UE4 C++】绘制函数 Debug drawing functions
基于UKismetSystemLibrary /** Draw a debug line */ UFUNCTION(BlueprintCallable, Category="Renderin ...
- UE4命令行使用,解释
命令行在外部 从命令行运行编辑项目 1 导航到您的[LauncherInstall][VersionNumber]\Engine\Binaries\Win64 目录中. 2 右键单击上 UE4Edit ...
- UE4 在C++ 动态生成几何、BSP体、Brush ---- Mesh_Generation
截至UE4 4.10 runtime 无法生成BSP类 ,只能通过自定义的Mesh的Vertex 进行绘制 ( Google 考证,能改UE4源码的请忽略 ) 可用到的 UE4 集成的Render ...
随机推荐
- #威佐夫博弈#洛谷 2252 [SHOI2002]取石子游戏
题目 有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子. 游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子: 二是可以在两堆中同时取走相同数量的石子.最后把石子全部取完 ...
- Python 中的数字类型与转换技巧
Python中有三种数字类型: int(整数) float(浮点数) complex(复数) 当您将值分配给变量时,将创建数字类型的变量: 示例:获取您自己的Python服务器 x = 1 # int ...
- JS启动Windows上的exe
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 重新整理数据结构与算法(c#)—— 二叉树排序树[二十二]
前言 什么是二叉堆排序呢? 就是上面这种,一个节点大于左节点,但是小于右节点,再我写的例子中会写出大于等于右节点. 那么如何让一个数组进行变成这种二叉树呢? 其实只要有规律就很简单. 第一个元素(0) ...
- Mysql安装和远程登录--Centos7
在Centos7中使用的包管理工具是yum,当然使用包管理工具安装也是最方便的. 本文操作内容需要在root用户下,否则有些步骤无法成功执行. 系统环境信息展示 安装 MySQL 提供的 RPM wg ...
- ddddocr基本使用和介绍
ddddocr基本使用和介绍 摘要:在使用爬虫登录网站的时候,经常输入用户名和密码后会遇到验证码,这时候就需要用到今天给大家介绍的python第三方库ddddocr,ddddocr是一款强大的通用开源 ...
- opensips使用drouting进行路由
操作系统 :CentOS 7.6_x64 opensips版本:2.4.9 drouting是Dynamic Routing(动态路由)的缩写,该模块可为特定呼叫选择(基于多个条件)最佳网关.今天整理 ...
- 使用Docker搭建MongoDB 5.0版本副本集集群
1.mongodb集群 首先我们需要了解mongodb的集群模式,mongodb安装分为单机安装和集群安装.集群安装分为:主从复制(Master-Slaver)集群.副本集(Replica Set)集 ...
- 阿里大数据云原生化实践,EMR Spark on ACK 产品介绍
开源大数据社区 & 阿里云 EMR 系列直播 第六期 主题:EMR spark on ACK 产品演示及最佳实践 讲师:石磊,阿里云 EMR 团队技术专家 内容框架: 云原生化挑战及阿 ...
- [GPT] Unable to negotiate with xx.xx.xx.xx port 22: no matching host key type found. Their offer: ssh-rsa,ssh-dss
这个错误通常发生在 SSH 客户端无法找到与 SSH服务器 匹配的主机密钥类型时. 这可能是因为SSH服务器配置为使用SSH客户端不支持的主机密钥类型. 要解决此问题,您需要将缺少的主机密钥类型添 ...