创建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. 从PRISM开始学WPF,Prism7更新了什么

    当时我在搬运Prism6.3的sample代码的时候,就是因为网上的资料太老旧,万万没想到这给自己挖了一个坑,因为我在做笔记的时候,prism已经在更新7.0了 现在已经是7.2了,(lll¬ω¬), ...

  2. springcloud情操陶冶-springcloud config server(三)

    承接前文springcloud情操陶冶-springcloud config server(二),本文就不讲述server了,就简单阐述下client的应用 前话 config server在引入的时 ...

  3. 第14章 纪元时间转换 - IdentityModel 中文文档(v1.0.0)

    JWT令牌使用所谓的Epoch或Unix时间来表示日期/时间. IdentityModel包含用于DateTime和DateTimeOffset转换到/来自Unix时间的扩展方法: var dt = ...

  4. .NET 平台上C#语言的基本技术点

    第一次用画图3D画的知识点,有点丑..........开始Csharp之路

  5. Sharepoint 2013内容查询Web部件自定义显示样式(实战)

    分享人:广州华软 星尘 一. 前言 在进行Sharepoint开发时,经常会遇到内容展示个性化需求的问题,当然如果通过自定义开发控件对于内容展示的需求基本都可以很好的解决,但自定义开发也有不好的地方, ...

  6. Android-----Intent中通过startActivity(Intent intent )显式启动新的Activity

    Intent:即意图,一般是用来启动新的Activity,按照启动方式分为两类:显式Intent 和 隐式Intent 显示Intent就是直接以“类名称”来指定要启动哪一个Activity:Inte ...

  7. LOJ #6060. 「2017 山东一轮集训 Day1 / SDWC2018 Day1」Set

    有趣的思博套路题,想到了基本上加上个对线性基的理解就可以过了 首先考虑到这个把数分成两半的分别异或的过程不会改变某一位上\(1\)的总个数 因此我们求出所有数的\(\operatorname{xor} ...

  8. java日志框架log4j详细配置及与slf4j联合使用教程

    最后更新于2017年02月09日 一.log4j基本用法 首先,配置log4j的jar,maven工程配置以下依赖,非maven工程从maven仓库下载jar添加到“build path” <d ...

  9. Harbor---docker镜像仓库搭建

    在用docker,kubernetes时registry是重要的一环,下面就来搭建一个镜像仓库.之前在公司时有资源域名,有做ssl证书,今天没条件就不做ssl证书和域名了. 1,下载 harbor 安 ...

  10. 认识音频格式-Au (NeXT/Sun)

    音频格式比较多, Au音频格式是一种被sun微处理器公司发明的一种简单的音频编码格式.日后一直在NEXT系统上使用,后面就演变成了一种标准的音频编码格式.目前很多音频设备上都支持这种编码格式.这种编码 ...