找回密码
 立即注册
查看: 272|回复: 0

Unity和Unreal Engine4的对应关系

[复制链接]
发表于 2022-11-6 15:00 | 显示全部楼层 |阅读模式
最近在学习UE4,以前用Unity比较多。在学习的翻阅官方文档时发现为了更方便地使开发者从Unity过度到UnrealEngine4,UE4官方专门给出了Unity各组件与UE4中的对应关系,可见Unity YYDS,我们将从以下两个方面参考官方文档对对应关系进行总结:基本条目和代码编写。下面是Unity和UE4的界面,图中已经将相同功能区域用相同颜色标注:



Unity的界面更简洁直观,UE4的图形化程度更高

基本条目

CategoryUnityUnreal
Editor UIScene ViewViewport
HierarchyWorld Outliner
InspectorDetails
Project BrowserContent Browser
ToolBarMain Toolbar
Right Click in HierarchyPlace Actors
Gameplay TypesComponent(List)Component(Level)
GameObjectActor(Pawn(Player or AI),Character(双足类型Pawn),Controller(占有并控制一个Pawn),Player Controller(输入设备信息驱动))
PrefabBlueprint Class
MeshesMeshStatic Mesh
Skinned MeshSkeletal Mesh
MaterialsShaderMaterial, Material Editor
MaterialMaterial Instance
EffectsParticle EffectEffect, Particle, Cascad
ShurikenCascade
Game UINGUI,UGUIUMG (Unreal Motion Graphics)
AnimationAnimationSkeletal Animation System
MecanimPersona , Animation Blueprint
2DSprite EditorPaper2D
ProgrammingC#C++
Script(MonoBehavior)Blueprint/C++
Start()BeginPlay()/InitializeComponent()
Update()Tick()/TickComponent()
OnDestroy()EndPlay()/UninitializeComponent()
PhysicsRaycastLine Trace, Shape Trace
Rigid BodyCollision, Physics
Runtime PlatformsiOS Player,Web PlayerPlatforms
Files.package.uproject
AssetContent
Save FormatSceneMap File
层级LayerCollision Channel
PhysicsRigidbodyPrimitive
测量单位厘米
坐标系左手坐标系左手坐标系,X 的正方向是"前",Y 的正方向是"右",Z 的正方向是"上"。
其中最大的区别就是UE4可以脱离C++脚本直接进行图形化编程,例如:虚幻 4 有一项很酷的功能,新建的 Actor 蓝图类会拥有自己的可视化蓝图脚本!这样你就能为整个对象添加逻辑,而不仅仅是单个组件,如新建一个Actor类
#pragma once
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"

UCLASS()class AMyActor : public AActor{
    GENERATED_BODY()
    int Count;

    // 为此Actor的属性设置默认值。
    AMyActor()
    {
        // Allows Tick() to be called
        PrimaryActorTick.bCanEverTick = true;  
    }

    // 当游戏开始或此Actor生成时调用。
    void BeginPlay()
    {
        Super::BeginPlay();
        Count = 0;
    }

    // 每帧调用。
    void Tick(float DeltaSeconds)
    {
        Super::Tick(DeltaSeconds);
        Count = Count + 1;
        GLog->Log(FString::FromInt(Count));
        }
    };`
则会经过编译生成相应的构造函数蓝图


Unity 的 prefab 和虚幻 4 的蓝图类都可以在游戏中实例化,不过Unity 的 prefab 在相互嵌套时会产生比较复杂的状况,从而限制其可扩展性;在虚幻 4 中,你可以让新建的蓝图类继承某个现有的蓝图类,然后通过新的属性、组件和可视化脚本功能来增强它。
代码编写

实例化GameObject /生成Actor
注意:C++ 中有些类以 "A" 开头,而其他一些类以 "U" 开头。前缀 "A" 代表它是 Actor 的子类,而前缀 "U" 代表它是 Object 的子类。还有其他一些前缀,比如 "F" 通常表示一个简单的数据结构类,或者其他非 Uboject 类。
Unity 中,创建对象可使用:
public class MyComponent : MonoBehaviour
{
    public int MyIntProp = 42;
    public SphereCollider MyCollisionComp = null;

    void Start()
    {
        // 创建碰撞组件(如果还未创建的话)
        if (MyCollisionComp == null)
        {
            MyCollisionComp = gameObject.AddComponent<SphereCollider>();
            MyCollisionComp.center = Vector3.zero;
            MyCollisionComp.radius = 20.0f;
        }
    }
}
使用 Instantiate 函数来新建对象的实例:
public GameObject EnemyPrefab;
public Vector3 SpawnPosition;
public Quaternion SpawnRotation;

void Start()
{
    GameObject NewGO = (GameObject)Instantiate(EnemyPrefab, SpawnPosition, SpawnRotation);
    NewGO.name = "MyNewGameObject";
}
在 Unity 中,如果要创建自己的 ScriptableObject 子类,你可以这样实例化:
MyScriptableObject NewSO = ScriptableObject.CreateInstance<MyScriptableObject>();
在虚幻 4 中,创建新对象可使用构造函数:
UCLASS()
class AMyActor : public AActor
{
    GENERATED_BODY()

    UPROPERTY()
    int32 MyIntProp;

    UPROPERTY()
    USphereComponent* MyCollisionComp;

    AMyActor()
    {
        MyIntProp = 42;

        MyCollisionComp = CreateDefaultSubobject<USphereComponent>(FName(TEXT("CollisionComponent"));
        MyCollisionComp->RelativeLocation = FVector::ZeroVector;
        MyCollisionComp->SphereRadius = 20.0f;
    }
};
NewObject 用于新建 UObject 类型的实例, 子类化 UObject 很像在 Unity 中子类化 ScriptableObject。它们适用于实现一些不需要在游戏中生成的类,或者不需要像Actor那样添加组件的类。如果要创建 UObject 的继承类,是像下面这样的初始化:
UMyObject* NewObj = NewObject<UMyObject>();
SpawnActor 用于新建 AActor 类型的实例,如NewObject 和 SpawnActor 函数也能通过给一个 "模板" 对象来工作:
AMyActor* CreateCloneOfMyActor(AMyActor* ExistingActor, FVector SpawnLocation, FRotator SpawnRotation)
{
    UWorld* World = ExistingActor->GetWorld();
    FActorSpawnParameters SpawnParams;
    SpawnParams.Template = ExistingActor;
    World->SpawnActor<AMyActor>(ExistingActor->GetClass(), SpawnLocation, SpawnRotation, SpawnParams);
}
销毁对象
Unity
Destroy(MyGameObject);
Unreal
MyActor->Destroy();
蓝图


禁用对象
Unity
MyGameObject.SetActive(false);
Unreal
MyActor->Destroy();
蓝图


通过组件访问GameObject/Actor
Unity
GameObject ParentGO = MyComponent.gameObject;
Unreal
AActor* ParentActor = MyComponent->GetOwner();
蓝图


通过 GameObject / Actor 访问组件
Unity
MyComponent MyComp = gameObject.GetComponent<MyComponent>();
Unreal
UMyComponent* MyComp = MyActor->FindComponentByClass<UMyComponent>();
蓝图


通过 GameObject / Actor 访问组件
Unity
// Find GameObject by name
GameObject MyGO = GameObject.Find("MyNamedGameObject");

// Find Objects by type
MyComponent[] Components = Object.FindObjectsOfType(typeof(MyComponent)) as MyComponent[];
foreach (MyComponent Component in Components)
{
// ...
}

// Find GameObjects by tag
GameObject[] GameObjects = GameObject.FindGameObjectsWithTag("MyTag");
foreach (GameObject GO in GameObjects)
{
// ...
}
Unreal
// Find Actor by name (also works on UObjects)
AActor* MyActor = FindObject<AActor>(nullptr, TEXT("MyNamedActor"));

// Find Actors by type (needs a UWorld object)
for (TActorIterator<AMyActor> It(GetWorld()); It; ++It)
{
AMyActor* MyActor = *It;
// ...
}
// Find UObjects by type
for (TObjectIterator<UMyObject> It; It; ++It)
{
UMyObject* MyObject = *It;
// ...
}

// Find Actors by tag (also works on ActorComponents, use TObjectIterator instead)
for (TActorIterator<AActor> It(GetWorld()); It; ++It)
{
AActor* Actor = *It;
if (Actor->ActorHasTag(FName(TEXT("Mytag"))))
{
// ...
}
}
蓝图




添加标签
Unity
MyGameObject.tag = "MyTag";Unreal
// Actors can have multiple tags
MyActor.Tags.AddUnique(TEXT("MyTag"));蓝图


比较标签
Unity
if (MyGameObject.CompareTag("MyTag"))
{
// ...
}

// Checks the tag on the GameObject it is attached to
if (MyComponent.CompareTag("MyTag"))
{
// ...
}Unreal
// Checks if an Actor has this tag
if (MyActor->ActorHasTag(FName(TEXT("MyTag"))))
{
// ...
}
// Checks if an ActorComponent has this tag
if (MyComponent->ComponentHasTag(FName(TEXT("MyTag"))))
{
// ...
}蓝图


触发器
Unity
public class MyComponent : MonoBehaviour{
void Start()
{
collider.isTrigger = true;
}
void OnTriggerEnter(Collider Other)
{
// ...
}
void OnTriggerExit(Collider Other)
{
// ...
}}
Unreal
UCLASS()class AMyActor : public AActor{
GENERATED_BODY()

// My trigger component
UPROPERTY()
UPrimitiveComponent* Trigger;

AMyActor()
{
Trigger = CreateDefaultSubobject<USphereComponent>(TEXT("TriggerCollider"));

// Both colliders need to have this set to true for events to fire
Trigger.bGenerateOverlapEvents = true;

// Set the collision mode for the collider
// This mode will only enable the collider for raycasts, sweeps, and overlaps
Trigger.SetCollisionEnabled(ECollisionEnabled::QueryOnly);
}
virtual void NotifyActorBeginOverlap(AActor* Other) override;

virtual void NotifyActorEndOverlap(AActor* Other) override;
};
蓝图


刚体运动
Unity
public class MyComponent : MonoBehaviour
{
    void Start()
    {
        rigidbody.isKinimatic = true;
        rigidbody.velocity = transform.forward * 10.0f;
    }
}
Unreal
在虚幻 4 中,碰撞组件和刚体组件是同一个组件,它的基类是 UPrimitiveComponent,
这个基类有很多不同的子类(USphereComponent,UCapsuleComponent 等)来配合不同的需求。
UCLASS()
class AMyActor : public AActor
{
    GENERATED_BODY()

    UPROPERTY()
    UPrimitiveComponent* PhysicalComp;

    AMyActor()
    {
        PhysicalComp = CreateDefaultSubobject<USphereComponent>(TEXT("CollisionAndPhysics"));
        PhysicalComp->SetSimulatePhysics(false);
        PhysicalComp->SetPhysicsLinearVelocity(GetActorRotation().Vector() * 100.0f);
    }
};
输入事件
Unity
public class MyPlayerController : MonoBehaviour{
void Update()
{
if (Input.GetButtonDown("Fire"))
{
// ...
}
float Horiz = Input.GetAxis("Horizontal");
float Vert = Input.GetAxis("Vertical");
// ...
}}
Unreal
UCLASS()class AMyPlayerController : public APlayerController{
GENERATED_BODY()

void SetupInputComponent()
{
Super::SetupInputComponent();

InputComponent->BindAction("Fire", IE_Pressed, this, &AMyPlayerController::HandleFireInputEvent);
InputComponent->BindAxis("Horizontal", this, &AMyPlayerController::HandleHorizontalAxisInputEvent);
InputComponent->BindAxis("Vertical", this, &AMyPlayerController::HandleVerticalAxisInputEvent);
}

void HandleFireInputEvent();
void HandleHorizontalAxisInputEvent(float Value);
void HandleVerticalAxisInputEvent(float Value);};
蓝图

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2025-2-23 02:47 , Processed in 0.093372 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表