创建Object

① 在uc脚本中使用new运算符来创建

/**********************************************************************************
outer : The value for the new object's Outer variable.
The default value is None, which means the object is created within the "transient package", a virtual package for runtime objects.
InName : The name for the new object.
flags : Specifies object flags for the new object.
class : The class to create an object of. No abstract object & No Actor.
**********************************************************************************/ new ( optional Object outer=none , optional String ObjName="" , optional int flags=0 ) class(template);

注1:outer记录当前object的创建者是谁

注2:new的实现在c++的UObject::execNew函数中

一些示例:

local TObject1 O1, O2, O3, O4;

O1 = new class'TObject1';
O2 = new(self) class'TObject1'; // O2.Outer=self
O3 = new(none, "TObject1_xxx") class'TObject1'; // O3.Name="TObject1_xxx"
O4 = new(self, "", 0) class'TObject1';

② 在c++中使用StaticConstructObject函数来创建

/**
* Create a new instance of an object. The returned object will be fully initialized. If InFlags contains RF_NeedsLoad (indicating that the object still needs to load its object data from disk), components
* are not instanced (this will instead occur in PostLoad()). The different between StaticConstructObject and StaticAllocateObject is that StaticConstructObject will also call the class constructor on the object
* and instance any components.
*
* @param Class the class of the object to create
* @param InOuter the object to create this object within (the Outer property for the new object will be set to the value specified here).
* @param Name the name to give the new object. If no value (NAME_None) is specified, the object will be given a unique name in the form of ClassName_#.
* @param SetFlags the ObjectFlags to assign to the new object. some flags can affect the behavior of constructing the object.
* @param Template if specified, the property values from this object will be copied to the new object, and the new object's ObjectArchetype value will be set to this object.
* If NULL, the class default object is used instead.
* @param Error the output device to use for logging errors
* @param SubobjectRoot
* Only used to when duplicating or instancing objects; in a nested subobject chain, corresponds to the first object that is not a subobject.
* A value of INVALID_OBJECT for this parameter indicates that we are calling StaticConstructObject to duplicate or instance a non-subobject (which will be the subobject root for any subobjects of the new object)
* A value of NULL indicates that we are not instancing or duplicating an object.
* @param InstanceGraph
* contains the mappings of instanced objects and components to their templates
*
* @return a pointer to a fully initialized object of the specified class.
*/
UObject* UObject::StaticConstructObject
(
UClass* InClass,
UObject* InOuter /*=GetTransientPackage()*/,
FName InName /*=NAME_None*/,
EObjectFlags InFlags /*=0*/,
UObject* InTemplate /*=NULL*/,
FOutputDevice* Error /*=GError*/,
UObject* SubobjectRoot /*=NULL*/,
FObjectInstancingGraph* InInstanceGraph /*=NULL*/
)
{
// ... ... // Allocate the object.
UObject* Result = StaticAllocateObject( InClass, InOuter, InName, InFlags, InTemplate, Error, NULL, SubobjectRoot, InstanceGraph ); if( Result )
{
{
// call the base UObject class constructor if the class is misaligned (i.e. a native class that is currently being recompiled)
// 调用UObject::InternalConstructor,里面会使用placement new来构造UObject,使得其能调用UObject()无参构造函数来初始化
if ( !InClass->IsMisaligned() )
{
(*InClass->ClassConstructor)( Result );
}
else
{
(*UObject::StaticClass()->ClassConstructor)( Result );
}
} // ... ...
} // ... ... return Result;
}

销毁Object

GC系统检查当前Object对象是否被Root类型Object对象直接或间接引用,如果没有则会销毁该Object

当某个Root类型Object不再使用某个Object对象时,应及时将其设置成null,来防止因为被引用无法及时被GC回收

注1:在UWorld::Tick中GC系统会按照一定的时间间隔调用UWorld::PerformGarbageCollection()来开始查找并标记那些对象是垃圾(GCMark),被标记的的object对象会触发BeginDestroy()调用

时间间隔变量TimeBetweenPurgingPendingKillObjects可以在*Engine.ini的[Engine.Engine]标签中配置,缺省配置为60秒

注2:在Tick中调用UObject::IncrementalPurgeGarbage(TRUE)分帧来回收垃圾(GCSweep),在delete Object前还会触发FinishDestroy()调用

由于Object是个对象,delete Object等价于:

Object->~Object();  // ~Object是个虚析构函数,不同Object类型对象会先调用自己的析构函数,然后依次调父类的
        operator delete(Object);

由于UObject实现了void operator delete( void* Object, size_t Size )成员函数,最后会调用UObject中的delete操作符重载函数

为了减少内存碎片和减少分配和回收内存开销,UE自己对UObject进行了内存管理,delete实际上不会真正地释放内存

注3:也可以通过执行obj gc来触发UObject::CollectGarbage( GARBAGE_COLLECTION_KEEPFLAGS )调用,来GCMark并GCSweep垃圾

注4:编辑器的GC引用分析逻辑在void FArchiveTagUsedNonRecursive::PerformReachabilityAnalysis( EObjectFlags KeepFlags )

游戏的在void FArchiveRealtimeGC::PerformReachabilityAnalysis( EObjectFlags KeepFlags )中

创建Actor

① 在uc脚本中使用Spawn函数来创建

' Spawn an actor. Returns an actor of the specified class, not of class Actor (this is hardcoded in the compiler). 
' Returns None if the actor could not be spawned (if that happens, there will be a log warning indicating why) Defaults to spawning at the spawner's location.
'
' @note: ActorTemplate is sent for replicated actors and therefore its properties will also be applied at initial creation on the client.
' However, because of this, ActorTemplate must be a static resource (an actor archetype, default object, or a bStatic/bNoDelete actor in a level package) or the spawned Actor cannot be replicated native noexport final function coerce actor Spawn
(
class<actor> SpawnClass,
optional actor SpawnOwner,
optional name SpawnTag,
optional vector SpawnLocation,
optional rotator SpawnRotation,
optional Actor ActorTemplate,
optional bool bNoCollisionFail
);

一些示例:

local UTBot NewBot;
local Pawn NewPawn;
local class<HUD> NewHUDType;
local HUD NewHUD; NewBot = Spawn(class'UTBot');
NewPawn = Spawn(class'UTPawn',,,vect(10.0,20.0,0.0),rot(1234, 5678 , 9012)); NewHUDType = class'UTEntryHUD';
NewHUD = Spawn(NewHUDType, self); //self为当前controller对象

注:Spawn的实现在c++的AActor::execSpawn函数中

② 在cpp中使用SpawnActor函数来创建

// Create a new actor. Returns the new actor, or NULL if failure.
AActor* UWorld::SpawnActor
(
UClass* Class,
FName InName=NAME_None,
const FVector& Location=FVector(,,),
const FRotator& Rotation=FRotator(,,),
AActor* Template=NULL,
UBOOL bNoCollisionFail=,
UBOOL bRemoteOwned=,
AActor* Owner=NULL,
APawn* Instigator=NULL,
UBOOL bNoFail=
)
{
// 游戏世界WorldInfo是否创建完毕
const UBOOL bBegunPlay = HasBegunPlay(); FVector NewLocation = Location;
// 根据Actor类型的碰撞信息和碰撞体大小调整Actor的位置
if( (Template->bCollideWorld || (Template->bCollideWhenPlacing && (GetNetMode() != NM_Client))) && !bNoCollisionFail )
{
FindSpot(Template->GetCylinderExtent(), NewLocation, Template->bCollideComplex);
} // 创建Actor
ULevel* LevelToSpawnIn = Owner ? CastChecked<ULevel>(Owner->GetOuter()) : CurrentLevel;
AActor* Actor = ConstructObject<AActor>( Class, LevelToSpawnIn, InName, RF_Transactional, Template );
// 添加Actor到关卡中
LevelToSpawnIn->Actors.AddItem( Actor );
// 添加Actor到关卡的Tick列表中
if (Actor->WantsTick())
{
LevelToSpawnIn->TickableActors.AddItem(Actor);
} Actor->bTicked = !Ticked;
Actor->CreationTime = GetTimeSeconds();
Actor->WorldInfo = GetWorldInfo(); // Set the actor's location and rotation.
Actor->Location = NewLocation;
Actor->Rotation = Rotation; // Initialize the actor's components.
Actor->ConditionalForceUpdateComponents(FALSE,FALSE); // init actor's physics volume
Actor->PhysicsVolume = GetWorldInfo()->PhysicsVolume; // Set owner.
Actor->SetOwner( Owner ); // Set instigator
Actor->Instigator = Instigator; if (bBegunPlay)
{
Actor->InitRBPhys();
} Actor->InitExecution();
Actor->Spawned(); if(bBegunPlay)
{
Actor->PreBeginPlay();
{
eventPreBeginPlay(); // 调用uc脚本的event PreBeginPlay()事件回调函数 // ... ...
} for(INT ComponentIndex = ;ComponentIndex < Actor->Components.Num();ComponentIndex++)
{
if(Actor->Components(ComponentIndex))
{
Actor->Components(ComponentIndex)->ConditionalBeginPlay();
}
}
} // Check for encroachment.
if( !bNoCollisionFail )
{
CheckEncroachment( Actor, Actor->Location, Actor->Rotation, );
}
else if ( Actor->bCollideActors )
{
Actor->FindTouchingActors();
} if(bBegunPlay)
{
Actor->PostBeginPlay();
{
// Send PostBeginPlay.
eventPostBeginPlay();// 调用uc脚本的event PostBeginPlay()事件回调函数 // Init scripting.
eventSetInitialState(); // 调用uc脚本的event SetInitialState()函数 // Find Base
if( !Base && bCollideWorld && bShouldBaseAtStartup && ((Physics == PHYS_None) || (Physics == PHYS_Rotating)) )
{
FindBase();
}
}
} if( InTick )
{
NewlySpawned.AddItem( Actor );
} return Actor;
}

销毁Actor

Actor本质还是一个Object,其回收是通过GC完成的,显示调用uc的Destory和cpp中的DestroyActor只是去除Actor对象的所有引用,让其能被GC视为垃圾

① 在uc脚本中使用Destory函数来销毁

'Destroy this actor. Returns true if destroyed, false if indestructible.
'Destruction is latent. It occurs at the end of the tick.
native() final noexport function k2call bool Destroy();

② 在cpp中使用DestroyActor函数来销毁

/**
* Removes the actor from its level's actor list and generally cleans up the engine's internal state.
* What this function does not do, but is handled via garbage collection instead, is remove references
* to this actor from all other actors, and kill the actor's resources. This function is set up so that
* no problems occur even if the actor is being destroyed inside its recursion stack.
*
* @param ThisActor Actor to remove.
* @param bNetForce [opt] Ignored unless called during play. Default is FALSE.
* @param bShouldModifyLevel [opt] If TRUE, Modify() the level before removing the actor. Default is TRUE.
* @return TRUE if destroy, FALSE if actor couldn't be destroyed.
*/
UBOOL UWorld::DestroyActor(
AActor* ThisActor,
UBOOL bNetForce=FALSE,
UBOOL bShouldModifyLevel=TRUE
)
{
check(ThisActor);
check(ThisActor->IsValid()); ThisActor->bPendingDelete = true; // Terminate any physics engine stuff for this actor right away.
ThisActor->TermRBPhys(NULL);
// Tell this actor it's about to be destroyed.
ThisActor->eventDestroyed();// 调用uc脚本的event Destroyed()事件回调函数
ThisActor->PostScriptDestroyed();
// Remove from base.
if( ThisActor->Base )
{
ThisActor->SetBase( NULL );
} // Make a copy of the array, as calling SetBase might change the contents of the array.
TArray<AActor*> AttachedCopy = ThisActor->Attached;
for( INT AttachmentIndex=; AttachmentIndex < AttachedCopy.Num(); AttachmentIndex++ )
{
AActor* AttachedActor = AttachedCopy(AttachmentIndex);
if( AttachedActor && AttachedActor->Base == ThisActor && !AttachedActor->bDeleteMe )
{
AttachedActor->SetBase( NULL );
}
}
// Then empty the array.
ThisActor->Attached.Empty(); // Clean up all touching actors.
INT iTemp = ;
for ( INT i=; i<ThisActor->Touching.Num(); i++ )
{
if ( ThisActor->Touching(i) && ThisActor->Touching(i)->Touching.FindItem(ThisActor, iTemp) )
{
ThisActor->EndTouch( ThisActor->Touching(i), );
i--;
}
} // If this actor has an owner, notify it that it has lost a child.
if( ThisActor->Owner )
{
ThisActor->SetOwner(NULL);
}
// Notify net players that this guy has been destroyed.
if( NetDriver )
{
NetDriver->NotifyActorDestroyed( ThisActor );
} // Remove the actor from the actor list.
RemoveActor( ThisActor, bShouldModifyLevel ); // Mark the actor and its direct components as pending kill.
ThisActor->bDeleteMe = ;
ThisActor->MarkPackageDirty();
ThisActor->MarkComponentsAsPendingKill( TRUE ); // Clean up the actor's components.
ThisActor->ClearComponents(); // Return success.
return TRUE;
}

UE3中Object和Actor的创建与销毁的更多相关文章

  1. Android中如何区分界面组件创建和销毁的类型

    本文主要描述: 1.分辨系统杀掉退出还是用户主动退出2.分辨全新的创建还是系统恢复性的创建 1.分辨系统杀掉退出还是用户主动退出 当一个组件失去焦点后,系统有可能为了释放资源而杀掉这个组件,这个时候系 ...

  2. Java中引用类型、对象的创建与销毁

    引用类型 在java中,除了基本数据类型之外的,就是引用数据类型了,引用指的是对象的一个引用,通过引用可以操作对象,控制对象,向对象发送消息. 简单来说,引用可以访问对象的属性,并调用对象的方法 创建 ...

  3. UE3中的时间

    为了管理时间,Unreal将游戏运行时间片分隔为"Ticks".一个Tick是关卡中所有Actors更新的最小时间单位.一个tick一般是10ms-100ms(CPU性能越好,游戏 ...

  4. python 中如何导入一个自己创建的模块

    导入模块的语句的三种方法: 1.import module 2.from module import name1,[name2,name3....] 3.from module import * 先看 ...

  5. JavaScript中Object的总结

    基于原型继承,动态对象扩展,闭包,JavaScript已经成为当今世界上最灵活和富有表现力的编程语言之一. 这里有一个很重要的概念需要特别指出:在JavaScript中,包括所有的函数,数组,键值对和 ...

  6. (转)es6中object.create()和object.assign()

    今天学习javascript面向对象,在学习Obejct方法时了解到create方法,偶像想起之前使用的assign方法,顺带查找一番,感觉这篇博客讲解详细,遂转载. 先简单提一下装饰器函数,许多面向 ...

  7. Javascript中Object常用方法学习

    1.Object.assign 函数(对象)(JavaScript) 将来自一个或多个源对象中的值复制到一个目标对象.语法: Object.assign(target, ...sources ); 此 ...

  8. js 中object对象的操作

    n = object对象 for(var p in n){ console.log(p);// 取得是key值 console.log(n[p]);//取得是value值 } 继之前js中数组的常用方 ...

  9. Java中Object的方法

    构造方法摘要Object()           方法摘要protected Object clone()           创建并返回此对象的一个副本.boolean equals(Object ...

随机推荐

  1. sun.misc jar包

    一直以来Base64算法的加密解密都是使用sun.misc包下的BASE64Encoder及BASE64Decoder来进行的.但是这个类是sun公司的内部方法,并没有在Java API中公开过,不属 ...

  2. ArcGIS API for JavaScript 入门教程[6] 再讲数据——Map类之可操作图层

    [回顾]上篇交代了Map是各种图层(不管是实际上的图层还是由图层构成的对象)的容器,是数据的容器,并不作显示(由视图类绘制).并重点讲解了由图层构成的复杂图层——高程属性ground和底图属性base ...

  3. GridView 的简单应用

    gridView 是android一个控件主要是显示列似与九宫格这样的效果.废话不多说直接上代码. 首先是需要一个适配器来确定每一个里面的布局,在里面我自定义了一个点击事件,当点击图片布局的时候触发, ...

  4. (三)图数据库neo4j的安装配置

    (一)neo4j安装 neo4j有社区版本和企业版,社区版本是免费的,企业版本是收费的.在linux上安装如下步骤: 1.将下载的neo4j-enterprise-3.4.0-unix.tar.gz包 ...

  5. oracle 简单备注

    1. 建立数据库 备注: 1) oracle 不同于mysql 可以直接create database 2) oracle 创建schema时对应一个用户,即该schema的访问用户,与用户一一对应: ...

  6. Mysql查询的一些操作(查表名,查字段名,查当月,查一周,查当天)

    查询数据库中所有表名 select table_name from information_schema.tables where table_schema='tools' and table_typ ...

  7. java虚拟机内存区域

    java虚拟机运行时数据 程序计数器 是一块较小的内存空间,属于线程私有的内存. 用来记录正在执行的虚拟机字节码指令的地址. 每个线程都需要一个独立的程序计数器,各个线程间的计数器互不影响,独立存储. ...

  8. 使用 JWT 生成 Token 代码示例

    JSON Web Token,简称 JWT, 是一个开放的标准(RFC 7519),它定义了以一种紧凑的.自包含的 JSON 对象在各方之间安全传输信息的方式.该信息含有数字签名,可以被验证和信任. ...

  9. Linux如何查看与测试磁盘IO性能

    1. 查看磁盘 IO 性能 1.1 top 命令 top 命令通过查看 CPU 的 wa% 值来判断当前磁盘 IO 性能,如果这个数值过大,很可能是磁盘 IO 太高了,当然也可能是其他原因,例如网络 ...

  10. .NET Core TDD 前传: 编写易于测试的代码 -- 缝

    有时候不是我们不想做单元测试, 而是这代码写的实在是没法测试.... 举个例子, 如果一辆汽车在产出后没完成测试, 那么没人敢去驾驶它. 代码也是一样的, 如果项目未能进行该做的测试, 那么客户就不敢 ...