UE4 C++学习

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_24835213/article/details/68483564

第一次在虚幻4上运用c++脚本。 

项目名要用英文!

继承BlueprintFunctionLibrary父类才可以在蓝图中调用

  • UFUNCTION(BlueprintPure,Category=" ??")
  • 继承自UBlueprintFunctionLibrary类中,凡是具备BlueprintCallable属性的UFUNTION即可在Blueprint中被调用
  • 如果UFUNCTION还带有BlueprintPure属性,那么意味着这个函数不会修改任何游戏状态,因此无需exec链的触发(在Blueprint中体现为没有白线输入),可以在任何时刻被调用获取其结果,作为随时可被调用的全局函数,都需要被声明成static函数
  • Category:方法所属类别
  •  
  • //声明一个静态方法

static TArry<int32> RamdomizeIntArry(TArray<int32> inputArry)

.cpp文件中的方法要和.h文件中类所继承的父类一样,如下图:

选择DebugGame Editor进行调试

调试的时候最好关闭虚幻编辑器 容易出现奇怪的错误

蓝图调用数据表:

1.数据表用Excel即可建立,导出为CSV格式。

2.在VS2013中定义结构体,代码如下:

ue4中文版蓝图中Squence节点的中文叫序列

创建新的渲染代理:

1.创建一个继承自PrimitiveComponent的C++组件类

2.头文件与cpp如下:

#pragma once
#include  "Engine.h"
#include "CoreMinimal.h"
#include "Components/PrimitiveComponent.h"
#include "UTestCustomComponent.generated.h"


UCLASS(meta=(BlueprintSpawnableComponent))
class UTestCustomComponent : public UPrimitiveComponent
{
	GENERATED_BODY()
public :
	virtual FPrimitiveSceneProxy* CreateSceneProxy() override;
	
	
	
};
#include "UTestCustomComponent.h"


class FTestCustomComponentSceneProxy : public FPrimitiveSceneProxy
{
public :
	FTestCustomComponentSceneProxy(UPrimitiveComponent* Component)
		:FPrimitiveSceneProxy(Component) {}
	virtual uint32 GetMemoryFootprint(void) const override {
		return (sizeof(*this) + GetAllocatedSize());
	}

	virtual void GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, class FMeshElementCollector& Collector)const override
	{
		FBox TestDynamicBox = FBox(FVector(-100.0f), FVector(100.0f));
		DrawWireBox(
			Collector.GetPDI(0),
			GetLocalToWorld(),
			TestDynamicBox,
			FLinearColor::Red,
			ESceneDepthPriorityGroup::SDPG_Foreground,
			10.0f);
	}

	virtual FPrimitiveViewRelevance GetViewRelevance(const FSceneView * View)const  override
	{
		FPrimitiveViewRelevance Result;
		Result.bDrawRelevance = IsShown(View);
		Result.bDynamicRelevance = true;
		Result.bShadowRelevance = IsShadowCast(View);
		Result.bEditorPrimitiveRelevance = UseEditorCompositing(View);
		return Result;

	}
};

FPrimitiveSceneProxy* UTestCustomComponent :: CreateSceneProxy()
{
	return new FTestCustomComponentSceneProxy(this);
}



实现结果如下:

总结:vs容易误报错误,其实编译可以通过,如下:

编译之后错误会消失。

创建静态渲染代理:

1.build.cs文件中引入新模块:

PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "Slate","SlateCore","InputCore", "HeadMountedDisplay" ,"RenderCore","ShaderCore","RHI"
        });


2.cpp文件如下:

// Fill out your copyright notice in the Description page of Project Settings.

#include "UTestCustomComponent.h"
#include "DynamicMeshBuilder.h"


/*Vertex Buffer*/
class FTestCustomComponentVertexBuffer : public FVertexBuffer
{
public:
	TArray<FDynamicMeshVertex> Vertices;

	virtual void InitRHI() override
	{
		FRHIResourceCreateInfo CreateInfo;
		void* VertexBufferData = nullptr;
		VertexBufferRHI = RHICreateAndLockVertexBuffer(Vertices.Num() * sizeof(FDynamicMeshVertex), BUF_Static, CreateInfo, VertexBufferData);
		FMemory::Memcpy(VertexBufferData, Vertices.GetData(), Vertices.Num() * sizeof(FDynamicMeshVertex));
		RHIUnlockVertexBuffer(VertexBufferRHI);
	}
};

/*Index Buffer*/
class FTestCustomComponentIndexBuffer : public  FIndexBuffer
{
public :
	TArray<int32> Indices;

	virtual void InitRHI() override
	{
		FRHIResourceCreateInfo CreateInfo;
		IndexBufferRHI = RHICreateIndexBuffer(sizeof(int32), Indices.Num() * sizeof(int32), BUF_Static, CreateInfo);
		void* Buffer = RHILockIndexBuffer(IndexBufferRHI, 0, Indices.Num() * sizeof(int32), RLM_WriteOnly);
		FMemory::Memcpy(Buffer, Indices.GetData(), Indices.Num() * sizeof(int32));
		RHIUnlockIndexBuffer(IndexBufferRHI);
	}
};

/*Vertex Factory*/
class FTestCustomComponentVertexFactory : public FLocalVertexFactory 
{
public:
	FTestCustomComponentVertexFactory()
	{ }
	/*Initialization*/
	void Init(const FTestCustomComponentVertexBuffer* VertexBuffer)
	{
		if (IsInRenderingThread())
		{
			//Initialize the vertex factory'sstream components
			DataType NewData;
			NewData.PositionComponent = STRUCTMEMBER_VERTEXSTREAMCOMPONENT(VertexBuffer, FDynamicMeshVertex, Position, VET_Float3);
			NewData.TextureCoordinates.Add(FVertexStreamComponent(VertexBuffer, STRUCT_OFFSET(FDynamicMeshVertex, TextureCoordinate), sizeof(FDynamicMeshVertex), VET_Float2));
			NewData.TangentBasisComponents[0] = STRUCTMEMBER_VERTEXSTREAMCOMPONENT(VertexBuffer, 
				FDynamicMeshVertex, TangentX, VET_PackedNormal);
			NewData.TangentBasisComponents[1] = STRUCTMEMBER_VERTEXSTREAMCOMPONENT(VertexBuffer, 
				FDynamicMeshVertex, TangentZ, VET_PackedNormal);
			SetData(NewData);
		}
		else
		{
			ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER(
			InitTestCustomComponentVertexFactor,
				FTestCustomComponentVertexFactory*, VertexFactory, this, const FTestCustomComponentVertexBuffer*, VertexBuffer, VertexBuffer, 
				{
					//Initialize the vertex factory's stream componnents,
					DataType NewData;
			NewData.PositionComponent = STRUCTMEMBER_VERTEXSTREAMCOMPONENT(
				VertexBuffer, FDynamicMeshVertex, Position, VET_Float3);
			NewData.TextureCoordinates.Add(FVertexStreamComponent(VertexBuffer, STRUCT_OFFSET(FDynamicMeshVertex, TextureCoordinate), sizeof(FDynamicMeshVertex), VET_Float2));
			NewData.TangentBasisComponents[0] = STRUCTMEMBER_VERTEXSTREAMCOMPONENT(VertexBuffer,
				FDynamicMeshVertex, TangentX, VET_PackedNormal);
			NewData.TangentBasisComponents[1] = STRUCTMEMBER_VERTEXSTREAMCOMPONENT(VertexBuffer,
				FDynamicMeshVertex, TangentZ, VET_PackedNormal);
			VertexFactory->SetData(NewData);
				});
		}
	}
};


class FTestCustomComponentSceneProxy : public FPrimitiveSceneProxy
{
public :
	FTestCustomComponentIndexBuffer  IndexBuffer;
	FTestCustomComponentVertexBuffer  VertexBuffer;
	FTestCustomComponentVertexFactory  VertexFactory;

public :
	FTestCustomComponentSceneProxy(UPrimitiveComponent* Component)
		:FPrimitiveSceneProxy(Component)
	{
		const float BoxSize = 100.0f;
		//填充顶点
		VertexBuffer.Vertices.Add(FVector(0.0F));
		VertexBuffer.Vertices.Add(FVector(BoxSize, 0.0f, 0.0f));
		VertexBuffer.Vertices.Add(FVector(0.0f, BoxSize, 0.0f));
		VertexBuffer.Vertices.Add(FVector(0.0f, 0.0f, BoxSize));
		//填充索引
		/*IndexBuffer.Indices.Add(0);
		IndexBuffer.Indices.Add(1);
		IndexBuffer.Indices.Add(2);
        */
		IndexBuffer.Indices.Add(0);
		IndexBuffer.Indices.Add(2);
		IndexBuffer.Indices.Add(3);

		IndexBuffer.Indices.Add(0); 
		IndexBuffer.Indices.Add(3);
		IndexBuffer.Indices.Add(1);

		/*IndexBuffer.Indices.Add(3);
		IndexBuffer.Indices.Add(2);
		IndexBuffer.Indices.Add(1);
		*/
		//初始化

		VertexFactory.Init(&VertexBuffer);
		BeginInitResource(&IndexBuffer);
		BeginInitResource(&VertexBuffer);
		BeginInitResource(&VertexFactory);
	}

	virtual ~FTestCustomComponentSceneProxy()
	{
		VertexBuffer.ReleaseResource();
		IndexBuffer.ReleaseResource();
		VertexFactory.ReleaseResource();
	}
	virtual uint32 GetMemoryFootprint(void) const override
	{
		return (sizeof(*this) + GetAllocatedSize());
	}


	virtual void GetDynamicMeshElements(const TArray<const FSceneView*>&
		Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, class FMeshElementCollector &Collector) const override
	{

		FBox TestDynamicBox = FBox(FVector(-100.0f), FVector(100.0f));
		DrawWireBox(
			Collector.GetPDI(0),
			GetLocalToWorld(),
			TestDynamicBox,
			FLinearColor::Black,
			ESceneDepthPriorityGroup::SDPG_Foreground,
			10.0f
		);
	}
	virtual FPrimitiveViewRelevance GetViewRelevance(const FSceneView*View)const override
	{
		FPrimitiveViewRelevance Result;
		Result.bDrawRelevance =true;
		Result.bStaticRelevance = true;
		Result.bDynamicRelevance = true;
		return Result;
	}

	virtual void DrawStaticElements(FStaticPrimitiveDrawInterface*PDI)override
	{
		FMeshBatch Mesh;
		FMeshBatchElement& BatchElement = Mesh.Elements[0];
		BatchElement.IndexBuffer = &IndexBuffer;
		Mesh.bWireframe = false;
		Mesh.VertexFactory = &VertexFactory;
		Mesh.MaterialRenderProxy = UMaterial::GetDefaultMaterial(MD_Surface)
			->GetRenderProxy(false);
		//Mesh->SetMaterial(0,);
		BatchElement.PrimitiveUniformBuffer = CreatePrimitiveUniformBufferImmediate(GetLocalToWorld(), GetBounds()
			, GetLocalBounds(), true, UseEditorDepthTest());
		BatchElement.FirstIndex = 0;
		BatchElement.NumPrimitives = IndexBuffer.Indices.Num() / 3;
		BatchElement.MinVertexIndex = 0;
		BatchElement.MaxVertexIndex = VertexBuffer.Vertices.Num() - 1;
		Mesh.ReverseCulling = IsLocalToWorldDeterminantNegative();
		Mesh.Type = PT_TriangleList;
		Mesh.DepthPriorityGroup = SDPG_Foreground;
		Mesh.bCanApplyViewModeOverrides = false;
		Mesh.bDisableBackfaceCulling = false;
		PDI->DrawMesh(Mesh, 1.0f);
	}
	};


FPrimitiveSceneProxy* UTestCustomComponent :: CreateSceneProxy()
{
	return new FTestCustomComponentSceneProxy(this);
}





效果如下:

在上一节的基础上绘制了一个静态模型,本来是一个三棱锥,被我改成了两个三角面,,基本上了解了通过c++绘制静态模型与动态模型的流程,但是依然无法做到修改静态模型的材质,达到双面显示的目的,有待学习。

了解了如何通过顶点缓冲区和索引缓冲区绘制模型的原理:

		const float BoxSize = 100.0f;
		//填充顶点
		VertexBuffer.Vertices.Add(FVector(0.0F));
		VertexBuffer.Vertices.Add(FVector(BoxSize, 0.0f, 0.0f));
		VertexBuffer.Vertices.Add(FVector(0.0f, BoxSize, 0.0f));
		VertexBuffer.Vertices.Add(FVector(0.0f, 0.0f, BoxSize));
		

上一段代码定义了四个顶点,索引分别为0,1,2,3.

		//填充索引
		IndexBuffer.Indices.Add(0);
		IndexBuffer.Indices.Add(1);
		IndexBuffer.Indices.Add(2);
               
                IndexBuffer.Indices.Add(0);
                IndexBuffer.Indices.Add(2);
		IndexBuffer.Indices.Add(3);

		IndexBuffer.Indices.Add(0); 
		IndexBuffer.Indices.Add(3);
		IndexBuffer.Indices.Add(1);

		IndexBuffer.Indices.Add(3);
		IndexBuffer.Indices.Add(2);
		IndexBuffer.Indices.Add(1);


上一段代码通过索引来定义了四个面并存储在了索引缓冲区中。

		Mesh.MaterialRenderProxy = UMaterial::GetDefaultMaterial(MD_Surface)
			->GetRenderProxy(false);


上一段代码定义了静态模型的材质,暂时还不知道怎么修改。

A绕B旋转C

A绕B旋转C

SetFloatingPointPropertyValue不起作用:

SetFloatingPointPropertyValue_not work

猜你喜欢

转载自blog.csdn.net/qq_24835213/article/details/68483564