{"id":1772,"date":"2021-06-16T17:46:06","date_gmt":"2021-06-16T09:46:06","guid":{"rendered":"http:\/\/bloo.heing.fun\/?p=1772"},"modified":"2021-06-16T17:47:02","modified_gmt":"2021-06-16T09:47:02","slug":"ue4-match3","status":"publish","type":"post","link":"https:\/\/bloo.heing.fun\/?p=1772","title":{"rendered":"UE4 Match3"},"content":{"rendered":"\n<pre class=\"wp-block-code\"><code># \u865a\u5e7b\u4e09\u6d88\n\n* actor\u83b7\u53d6gamemode\n\n```\nCast&lt;AMatch3GameMode>(UGameplayStatics::GetGameMode(WorldContextObject))\n\u8fd9\u4e2aWorldContextObject\u4f20AActor this\u5c31\u884c\u4e86\n```\n\n* spawned actor\u83b7\u53d6spawn\u81ea\u5df1\u7684actor\n\n```\nFActorSpawnParameters SpawnParams;\nSpawnParams.Owner = this;\nSpawnParams.Instigator = GetInstigator();\nSpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;\n\/\/ Tiles never rotate\nFRotator SpawnRotation(0.0f, 0.0f, 0.0f);\n\/\/ Spawn the tile.\nATile* const NewTile = World->SpawnActor&lt;ATile>(TileToSpawn, SpawnLocation, SpawnRotation, SpawnParams);\n\n\u7136\u540espawned actor:\nGrid = Cast&lt;AGrid>(GetOwner());            \n\t\t\t\n```\n\n* GameInstance\u4f7f\u7528\n\t* \u5728Edit->Project Settings->Project->Maps &amp; Modes\u91cc\u914d\u7f6e\u7528\u81ea\u5df1\u7684GameInstance\u7c7b\n\t* GameInstance\u590d\u5199\u7236\u7c7b\u65b9\u6cd5\uff1a\n\t\n    ```\n    \n\t\/\/ Called by the game at startup.\n\tvoid Init() override;\n\n\t\/\/ Called by the game as it shuts down.\n\tvoid Shutdown() override;\n    ```\n    \u5728\u8fd9\u4e24\u4e2a\u51fd\u6570\u5b9e\u73b0\u4e2d\uff0c\u5148\u5199\u81ea\u5df1\u7684\u81ea\u5b9a\u4e49\u5b9e\u73b0\uff0c\u6700\u540e\u518d\u8c03\u7528\u7236\u7c7b\u5b9e\u73b0Super::F()\n    \n    * GameInstance\u6709\u4e2aUSaveGame\u4f5c\u4e3a\u6210\u5458\u53d8\u91cf\uff0c\u5728\u5176\u4ed6\u5730\u65b9\u4e0d\u64cd\u4f5cUSaveGame\uff0c\u6240\u6709\u6709\u5173\u7684\u64cd\u4f5c\u90fd\u901a\u8fc7GameInstance\u76f4\u63a5\u6216\u95f4\u63a5\u8fdb\u884c\u3002\n    \t* \u6bcf\u4e2alevel\u7684slotname\u90fd\u662f\u5173\u5361\u540d \n    \t*  \u6709\u4e2a\u3010TMap FString, int32\u3011\u8bb0\u5f55\u4e00\u4e9b\u4e1c\u897f\uff0c\u5982\u5206\u6570\uff0c\u662f\u5426\u64ad\u653e\u97f3\u4e50(\u5c06int32\u8f6c\u4e3abool)\n\n\t* GameInstance\u7684init\u91cc\u9762\uff0c\u6ce8\u518c\u4e86\u4e00\u4e9b\u4e8b\u4ef6\n\t\n    ```\n    LoginChangedHandle = FCoreDelegates::OnUserLoginChangedEvent.AddUObject(this, &amp;UMatch3GameInstance::OnLoginChanged);\n\tEnteringForegroundHandle = FCoreDelegates::ApplicationHasEnteredForegroundDelegate.AddUObject(this, &amp;UMatch3GameInstance::OnEnteringForeground);\n\tEnteringBackgroundHandle = FCoreDelegates::ApplicationWillEnterBackgroundDelegate.AddUObject(this, &amp;UMatch3GameInstance::OnEnteringBackground);\n\tViewportHandle = FViewport::ViewportResizedEvent.AddUObject(this, &amp;UMatch3GameInstance::OnViewportResize_Internal);\n\n    ```\n    \n  * \u83b7\u53d6GameInstance\n  \n  ```\n   UGameInstance* GameplayStatics::GetGameInstance(const UObject* WorldContextObject);\n  ```\n \n * \u6e38\u620f\u7684\u8bbe\u7f6e\uff08\u662f\u5426\u64ad\u653e\u58f0\u97f3\u3001\u662f\u5426\u64ad\u653e\u97f3\u4e50\u7b49\u8bbe\u7f6e\uff09\u4e5f\u4f5c\u4e3a\u6210\u5458\u53d8\u91cf\u8bb0\u5f55\u5728GameInstance\u91cc\uff0c\u63a5\u7740\u5728\u5bf9\u5e94\u60c5\u51b5\u65f6\u68c0\u67e5GameInstance\u7684\u8bbe\u7f6e\u3002\n \n* \u83b7\u53d6\u5f53\u524dLevel\u7684\u540d\u5b57\n\n```\n\/**\n\t* Get the name of the currently-open level.\n\t*\n\t* @param bRemovePrefixString\tremove any streaming- or editor- added prefixes from the level name.\n\t*\/\n\tUFUNCTION(BlueprintCallable, meta = (WorldContext = \"WorldContextObject\", AdvancedDisplay = \"1\"), Category = \"Game\")\n\tstatic FString GameplayStatics::GetCurrentLevelName(const UObject* WorldContextObject, bool bRemovePrefixString = true);\n```\n\n* \u68cb\u76d8\u751f\u6210\u7b97\u6cd5\n\n\u4ee5\u5f53\u524dActor\u4e3a\u4e2d\u5fc3\uff0c\u5de6\u4e0b\u89d2\u4e3a0\n```\nFVector AGrid::GetLocationFromGridAddress(int32 GridAddress) const\n{\n\tFVector Center = GetActorLocation();\n\tFVector OutLocation = FVector(-(GridWidth * 0.5f) * TileSize.X + (TileSize.X * 0.5f), 0.0f, -(GridHeight * 0.5f) * TileSize.Y + (TileSize.Y * 0.5f));\n\tcheck(GridWidth > 0);\n\tOutLocation.X += TileSize.X * (float)(GridAddress % GridWidth);\n\tOutLocation.Z += TileSize.Y * (float)(GridAddress \/ GridWidth);\n\tOutLocation += Center;\n\n\treturn OutLocation;\n}\n```\n\n* GameMode\n\t* \u91cd\u542f\u5f53\u524d\u5173\u5361\n\n\t```\n    \n\tFName LevelName(*UGameplayStatics::GetCurrentLevelName(this, true));\n\tUGameplayStatics::OpenLevel(this, LevelName);\n    ```\n\n\t* \u5b9e\u73b0UserWidget\u7684\u5207\u6362\n\n\t```\n    void AMatch3GameMode::ChangeMenuWidget(TSubclassOf&lt;UUserWidget> NewWidgetClass)\n{\n\tif (CurrentWidget)\n\t{\n\t\tCurrentWidget->RemoveFromViewport();\n\t\tCurrentWidget = nullptr;\n\t}\n\tif (NewWidgetClass)\n\t{\n\t\tif (AMatch3PlayerController* PC = Cast&lt;AMatch3PlayerController>(UMatch3BlueprintFunctionLibrary::GetLocalPlayerController(this)))\n\t\t{\n\t\t\tCurrentWidget = CreateWidget&lt;UUserWidget>(PC, NewWidgetClass);\n\t\t\tif (CurrentWidget)\n\t\t\t{\n\t\t\t\tCurrentWidget->AddToViewport();\n\t\t\t}\n\t\t}\n\t}\n    ```\n\t* IsGameActive()\n\n\t```\nbool AMatch3GameMode::IsGameActive() const\n{\n\t\/\/ Game is active whenever time hasn't run out or the timer is paused.\n\tFTimerManager&amp; WorldTimerManager = GetWorldTimerManager();\n\treturn (WorldTimerManager.IsTimerActive(GameOverTimer) || WorldTimerManager.IsTimerPaused(GameOverTimer));\n}\n\t```\n\n\t* GetRemainingTime\n\n\t```\nGetWorldTimerManager().GetTimerRemaining(GameOverTimer)\n\t```\n\n\t* \u7ed9\u8ba1\u65f6\u5668\u52a0\u65f6\u95f4\n\n\t```\n    \u91cd\u65b0\u8bbe\u7f6e\u4e0btimer\u5c31\u597d\n    GetWorldTimerManager().SetTimer(GameOverTimer, this, &amp;AMatch3GameMode::GameOver, StartingTimeValue + (ScoreAwardCount * Reward.TimeAwarded), false);\n\t\t\t\t\t\n    ```\n    \n    * GameMode\u4e00\u822c\u548cPlayerController\u6253\u4ea4\u9053\n\n* PlayerController->IsLocalController()\n* the network to uniquely identify a player:\n\n```\nPlayerController->PlayerState->GetUniqueId()->GetHexEncodedString()\n```\n\n* \u4ea4\u6362\u5b9d\u77f3\u65f6\u90a3\u79cd\u4f4d\u7f6e\u79fb\u52a8\u7684\u52a8\u753b\uff0c\u901a\u8fc7\u8282\u70b9Timeline\u5728\u4e24\u4e2a\u4f4d\u7f6e\u4e2dlerp\u5b9e\u73b0<\/code><\/pre>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[87,36],"tags":[],"class_list":["post-1772","post","type-post","status-publish","format-standard","hentry","category-ue4","category-36"],"_links":{"self":[{"href":"https:\/\/bloo.heing.fun\/index.php?rest_route=\/wp\/v2\/posts\/1772","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bloo.heing.fun\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bloo.heing.fun\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bloo.heing.fun\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bloo.heing.fun\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1772"}],"version-history":[{"count":2,"href":"https:\/\/bloo.heing.fun\/index.php?rest_route=\/wp\/v2\/posts\/1772\/revisions"}],"predecessor-version":[{"id":1774,"href":"https:\/\/bloo.heing.fun\/index.php?rest_route=\/wp\/v2\/posts\/1772\/revisions\/1774"}],"wp:attachment":[{"href":"https:\/\/bloo.heing.fun\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1772"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bloo.heing.fun\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1772"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bloo.heing.fun\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1772"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}