本文最后更新于:2024年9月1日 晚上
[toc]
PuerTS的常用写法,
TS基础写法 TypeScript 教程 | 菜鸟教程 (runoob.com)
基础类型 · TypeScript中文网 · TypeScript——JavaScript的超集 (tslang.cn)
变量 1 private PlayStateCheckHandle : TimerHandle | undefined = undefined ;
|表示联合类型,表示既可以是TimerHandle也可以是undefined
对象 1 Proto _Nodes : { [k : string ]: Aki .Protocol .IProto_NodeInfo };
表示一个索引签名(index signature),用于定义一个对象类型,其中键(key)是字符串类型,而值(value)是 Aki.Protocol.IProto_NodeInfo
类型。
函数 可变长参数
…args
1 2 3 4 5 6 7 8 function myFunction (first: number , ...rest: string [] ) { console .log (`First argument is ${first} ` ); for (let arg of rest) { console .log (arg); } }myFunction (1 , 'hello' , 'world' , '!' );
在 TypeScript 中,函数内部创建的局部变量确实可以返回并在函数外部被直接修改,但这通常适用于可变类型(mutable types),如对象(包括 Map
、Set
、数组等)和函数。对于不可变类型(immutable types),如原始数据类型(数字、字符串、布尔值等),则不能直接修改。
可变类型:
当函数返回一个可变类型的值时,实际上返回的是这个值的引用(reference)。因此,通过这个引用所做的任何修改都会反映到原始对象上。
1 2 3 4 5 6 7 8 复制function createObject() { const obj = { prop : 1 }; return obj; }const myObj = createObject(); myObj.prop = 2; console.log (myObj.prop );
这个是因为看的时候看到一段对我来说比较吊诡的代码,在一个私有函数创建了一个map(nodes),直接set到了另一个map(NodesGroupByStatus)里面,但是直接返回nodes,在另一个函数里面可以直接修改,后面查了才知道,ts如果返回maps这种可修改的变量相当于返回的是引用,所以就是改的原始的nodes
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 private AddNodeGroup (group : ENodeGroup ): Map <number , TBehaviorNode > { const nodes = new Map <number , TBehaviorNode >(); this .NodesGroupByStatus !.set (group, nodes); return nodes; }public AddNodeToStatusGroup (node : TBehaviorNode , newStatus : Aki .Protocol .Proto_NodeStatus ): void { const groupId = this .GetGroupIdByStatus (newStatus); let nodes = this .GetNodesByGroupId (groupId); if (!nodes) { nodes = this .AddNodeGroup (groupId); } nodes.set (node.NodeId , node); }
类 继承extends
super关键字
调用父类构造函数 :当你定义一个子类时,如果需要调用其父类的构造函数,可以使用 super()
。这是必须的步骤,因为子类的实例在JavaScript/TypeScript中总是通过父类的构造函数创建的。
访问父类成员 :super
也可以用来访问父类中定义的属性和方法,这在你想要扩展或重写父类成员时非常有用。
访问父类的静态成员 :使用 super
关键字,也可以访问父类的静态属性或方法
在构造函数中 :在构造函数中使用 super
必须作为第一条语句,因为子类实例的创建是基于父类构造函数的。
在派生类的静态方法中 :在静态方法中使用 super
来访问父类的静态成员。
在派生类的方法中 :在非静态方法中使用 super
来访问父类的非静态成员。
泛型 委托 一开始看这个OnUpdate的时候非常懵逼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 OnUpdate (newUpdate : $Undefinable<$Delegate<(InProgress: number ) => void >>) : $Undefinable<LTweener >; protected override OnTick (deltaTime : number ): void { const tween = this .TextPlayTweenComp !.GetPlayTween () as UE .LGUIPlayTween_Int ; const tweener = tween?.GetTweener (); if (tweener) { tweener.OnUpdate ( toManualReleaseDelegate ((progress : number ): void => { const pro = Math .round (progress * (tween.to - tween.from )) + tween.from ; if (this .Progress < pro) { this .Progress = pro; this .GetText (EDigitalScreenView .TextList )?.SetText (this .Text .substring (0 , this .Progress )); } }), ); } }
运算符 as 基础类型 · TypeScript中文网 · TypeScript——JavaScript的超集 (tslang.cn)
类型断言,有点类似其他语言的类型转换,通常这会发生在你清楚地知道一个实体具有比它现有类型更确切的类型。
1 2 3 let someValue : any = "this is a string" ;let strLength : number = (someValue as string ).length ;
三元运算符 const id = a ? b : c;
条件 ? 表达式1 : 表达式2
如果 条件
(在这里是变量 a
)为真(truthy),那么整个表达式的结果是 表达式1
(在这里是变量 b
)。
如果 条件
为假(falsy),那么结果是 表达式2
(在这里是变量 c
)。
==和===和!==
严格等于 (===
) :
===
是严格等于运算符,它比较两个值是否完全相等,包括它们的类型。
如果两个操作数的类型不同,===
返回 false
。
只有当两个操作数的类型和值都相同时,===
才返回 true
。
等于 (==
) :
==
是等于运算符,它比较两个值是否等价。
如果操作数的类型不同,JavaScript 会进行类型转换,然后再比较它们的值。
==
会根据需要将操作数转换为数字或字符串,然后进行比较。
!==
不相等,但是不会进行类型转换
?.和!. !
被称为非空断言操作符,它用来告诉 TypeScript 编译器,某个位置的值不应该为 null
或 undefined
。
?.是一种语法糖, 如果多层访问中间有null或者undefined就会返回undefined,不用自己再另写类型检查
?: 表示调用这个对象或者参数的时候这个参数可选
?? 逻辑运算符,用于返回两个操作数中第一个非空值(non-nullish value),或者在两个操作数都为空值(null 或 undefined)时返回右侧的操作数。
UE4容器使用 TArray TArray:虚幻引擎中的数组 | 虚幻引擎4.26文档 (unrealengine.com)
创建和填充 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 TArray<int32> IntArray; IntArray.Init (10 ,5 ); TArray<FString> StrArr; StrArr.Add (TEXT ("Hello" )); StrArr.Emplace (TEXT ("World" )); FString Arr[] = { TEXT ("of" ), TEXT ("Tomorrow" ) }; StrArr.Append (Arr, ARRAY_COUNT (Arr)); StrArr.AddUnique (TEXT ("!" )); StrArr.AddUnique (TEXT ("!" )); StrArr.Insert (TEXT ("Brave" ), 1 );
迭代 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 FString JoinedStr;for (auto & Str :StrArr) { JoinedStr+=Str; }for (int32 Index = 0 ; Index != StrArr.Num (); ++Index) { JoinedStr += StrArr[Index]; JoinedStr += TEXT (" " ); }for (auto It = StrArr.CreateConstIterator ();It;++It) { JoinedStr += *It; JoinedStr += TEXT (" " ); }
排序
查询 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 bool bHello = StrArr.Contains (TEXT ("Hello" ));bool bGoodbye = StrArr.Contains (TEXT ("Goodbye" ));bool bLen5 = StrArr.ContainsByPredicate ([](const FString& Str){ return Str.Len () == 5 ; });bool bLen6 = StrArr.ContainsByPredicate ([](const FString& Str){ return Str.Len () == 6 ; }); int32 IndexLast;if (StrArr.FindLast (TEXT ("Hello" ), IndexLast)) { } int32 Index2 = StrArr.Find (TEXT ("Hello" )); int32 IndexLast2 = StrArr.FindLast (TEXT ("Hello" )); int32 IndexNone = StrArr.Find (TEXT ("None" ));auto Filter = StrArray.FilterByPredicate ([](const FString& Str){ return !Str.IsEmpty () && Str[0 ] < TEXT ('M' ); });
移除
运算符 1 2 3 4 5 6 7 8 ValArr3 = MoveTemp (ValArr4);
堆 Slack 内存 TMap TMap | 虚幻引擎4.27文档 (unrealengine.com)
TMap键不能重复,TMultiMap键不唯一
创建和填充 1 2 3 4 TMap<int32, FString> FruiMap;
迭代 类似TArrays,不过迭代元素是TPair
查询 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 FString& Ref7 = FruitMap.FindOrAdd (7 ); FString& Ref8 = FruitMap.FindOrAdd (8 ); FString Val7 = FruitMap.FindRef (7 ); FString Val6 = FruitMap.FindRef (6 );
移除 1 2 3 4 5 6 7 8 9 FruitMap.Remove (8 ); FString Removed7 = FruitMap.FindAndRemoveChecked (7 ); FString Removed;bool bFound2 = FruitMap.RemoveAndCopyValue (2 , Removed);
排序 1 2 3 4 FruitMap.KeySort ([](int32 A, int32 B) { return A > B; });
运算符 有复制和移动语义
Slack KeyFuncs TSet UE4回调 委托 | 虚幻引擎4.26文档 (unrealengine.com)
一文理解透UE委托Delegate - 知乎 (zhihu.com)
UE支持三种委托:单点委托,组播委托(事件),动态委托
单点委托 多播 动态委托 UE4对象函数 UFunctions | 虚幻引擎4.26文档 (unrealengine.com)
UE4引用 引用资源 | 虚幻引擎4.26文档 (unrealengine.com)
引用 Actor | 虚幻引擎4.26文档 (unrealengine.com)
UE引用类型说明 - 飞书云文档 (feishu.cn)
引用分为两种,硬性引用,即对象 A 引用对象 B,并导致对象 B 在对象 A 加载时加载;软性引用,即对象 A 通过间接机制(例如字符串形式的对象路径)来引用对象 B。
一种是通过UPROPERTY
直接属性引用
通过设置变量的UPROPERTY直接在编辑器设置对应资源
1 2 3 4 5 UPROPERTY (EditDefaultsOnly, Category=Building) USoundCue* ConstructionStartStinger;
构造时引用
构造时加载对应资源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 UPROPERTY() class UTexture2D* BarFillTexture; AStrategyHUD::AStrategyHUD(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { static ConstructorHelpers::FObjectFinder<UTexture2D> BarFillObj(TEXT("/Game/UI/HUD/BarFill" ) ); ... BarFillTexture = BarFillObj.Object; ... }
一种是用字符串来引用,如果UObject已经加载就用FindObject<>(),没有加载就使用LoadObject<>()
1 2 AFunctionalTest* TestToRun = FindObject <AFunctionalTest>(TestsOuter, *TestName); GridTexture = LoadObject <UTexture2D>(NULL , TEXT ("/Engine/EngineMaterials/DefaultWhiteGrid.DefaultWhiteGrid" ), NULL , LOAD_None, NULL );
UE4FName FName | 虚幻引擎4.26文档 (unrealengine.com)
在 内容浏览器 中为新资源命名时,变更动态材质实例中的参数或访问骨骼网格体中的一块骨骼时需要使用 FNames 。 FName 通过一个轻型系统使用字符串。在此系统中,特定字符串即使会被重复使用,在数据表中也只存储一次。
FNames 不区分大小写。它们为不可变,无法被操作。FNames 的存储系统和静态特性决定了通过键进行 FNames 的查找和访问速度较快。 FName 子系统的另一个功能是使用散列表为 FName 转换提供快速字符串。
FNames 不区分大小写,作为索引组合存储在唯一字符串和实例编号的表格中。
创建 1 FName TestName = FName (TEXT ("Test" ));
转换 1 2 3 4 5 6 7 8 9 10 11 12 TestString = TestName.ToSring (); TestText = FText::FromName (TestName); TestName = FName (*TextString);
对比是否相同直接比较索引的数值,不用执行字符串的对比