(Feat) Fix Fade Loading
This commit is contained in:
@@ -28,6 +28,7 @@ class SURVIVAL_PROJET_API USurvivalGameInstance : public UGameInstance
|
||||
|
||||
public:
|
||||
virtual void Init() override;
|
||||
virtual void Shutdown() override;
|
||||
|
||||
/** Nom de la derniere camera de menu utilisee. NAME_None au premier lancement. */
|
||||
UFUNCTION(BlueprintPure, Category = "Menu")
|
||||
@@ -50,7 +51,87 @@ public:
|
||||
UFUNCTION(BlueprintCallable, Category = "Input")
|
||||
void RegisterMappableContexts();
|
||||
|
||||
/**
|
||||
* Un depart VOULU vers le menu commence : le filet de secours reseau doit
|
||||
* se taire.
|
||||
*
|
||||
* Sans ce drapeau, la connexion qui tombe pendant le fondu de sortie
|
||||
* declencherait HandleNetworkFailure, qui chargerait le menu sur-le-champ
|
||||
* et couperait le fondu en plein milieu -- exactement le saut d'image qu'on
|
||||
* cherchait a eviter en fondant.
|
||||
*/
|
||||
void BeginReturnToMainMenu() { bReturningToMainMenu = true; }
|
||||
|
||||
/** On est arrive au menu : le filet redevient actif pour la partie suivante. */
|
||||
void ClearReturnToMainMenu() { bReturningToMainMenu = false; }
|
||||
|
||||
/**
|
||||
* Rend la main au rendu du monde, coupe depuis le chargement de la map.
|
||||
*
|
||||
* A n'appeler QUE lorsque le voile de fondu est deja noir : le monde
|
||||
* reapparait alors derriere lui, invisible.
|
||||
*
|
||||
* Pourquoi couper le rendu plutot que poser un widget. Mesure sur une vraie
|
||||
* connexion : 2,4 secondes s'ecoulent entre `LoadMap` chez le client et la
|
||||
* naissance de son PlayerController, que le serveur lui envoie. Pendant ce
|
||||
* temps la map est chargee et le moteur la rend depuis une vue par defaut --
|
||||
* sous le terrain. Il n'existe alors AUCUN acteur a qui accrocher un voile,
|
||||
* et le composant de fondu vit justement sur ce controller absent. Le
|
||||
* viewport, lui, survit aux changements de map et n'appartient a personne.
|
||||
*
|
||||
* Attend aussi la fin du streaming avant de rendre la main : c'est le seul
|
||||
* instant du chargement ou l'on sait que rien ne sera montre tant qu'on n'a
|
||||
* pas fini. Sans ca, le joueur voit le terrain passer de sa version
|
||||
* grossiere a la vraie, et les modeles apparaitre un a un.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Chargement")
|
||||
void ResumeWorldRendering();
|
||||
|
||||
/**
|
||||
* Laisse le monde rendre SceneWarmupFrames images derriere le voile noir,
|
||||
* puis rappelle OnComplete.
|
||||
*
|
||||
* Compte des IMAGES et non des secondes, et c'est tout l'interet. Ce qui
|
||||
* reste a se raffiner apres le flush de streaming -- Nanite, les ombres
|
||||
* virtuelles, la convergence de Lumen -- progresse a chaque image RENDUE,
|
||||
* pas avec le temps qui passe. Une duree fixe donnerait quarante images sur
|
||||
* une machine rapide et cinq sur une machine lente : exactement celle qui en
|
||||
* aurait eu le plus besoin.
|
||||
*/
|
||||
void BeginSceneWarmup(FSimpleDelegate OnComplete);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Temps maximal accordé au streaming avant de montrer le monde, en secondes.
|
||||
*
|
||||
* Ce blocage se produit ECRAN NOIR, donc il ne se voit pas -- c'est du temps
|
||||
* de chargement, pas une saccade. Le dépasser vaut mieux que de montrer un
|
||||
* terrain qui se raffine sous les yeux du joueur, mais on le borne quand
|
||||
* même : une machine lente ne doit pas rester bloquée indéfiniment.
|
||||
*
|
||||
* Réglable sur BP_SurvivalGameInstance.
|
||||
*/
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Chargement", meta = (ClampMin = "0", Units = "s"))
|
||||
float StreamingFlushTimeLimit = 5.f;
|
||||
|
||||
/**
|
||||
* Nombre d'images rendues derriere le voile noir avant de l'eclaircir.
|
||||
* Voir BeginSceneWarmup(). Reglable sur BP_SurvivalGameInstance.
|
||||
*/
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Chargement", meta = (ClampMin = "0"))
|
||||
int32 SceneWarmupFrames = 45;
|
||||
|
||||
/**
|
||||
* Plafond de la chauffe, en secondes.
|
||||
*
|
||||
* Le compte d'images reste la mesure PRINCIPALE -- c'est la bonne unite.
|
||||
* Ceci n'est qu'un garde-fou : sur une machine tres lente, 45 images
|
||||
* pourraient prendre plusieurs secondes d'ecran noir, et mieux vaut un
|
||||
* decor pas tout a fait converge qu'une attente qui inquiete.
|
||||
*/
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Chargement", meta = (ClampMin = "0.1", Units = "s"))
|
||||
float SceneWarmupMaxSeconds = 2.f;
|
||||
|
||||
/**
|
||||
* Les mapping contexts dont les touches sont remappables. Mets-y IMC_Default.
|
||||
*
|
||||
@@ -63,6 +144,70 @@ protected:
|
||||
TArray<TObjectPtr<UInputMappingContext>> MappableContexts;
|
||||
|
||||
private:
|
||||
/**
|
||||
* L'hote a quitte, ou la connexion est tombee.
|
||||
*
|
||||
* Sans ce filet, un client dont l'hote ferme le jeu reste planté dans un
|
||||
* monde qui ne repond plus : le moteur coupe la connexion, mais rien ne le
|
||||
* ramene nulle part. C'est ici et pas sur le PlayerController parce que
|
||||
* celui-ci est justement detruit par l'echec -- le GameInstance est le seul
|
||||
* objet dont on soit certain qu'il vive encore a cet instant.
|
||||
*/
|
||||
void HandleNetworkFailure(UWorld* World, UNetDriver* NetDriver, ENetworkFailure::Type FailureType, const FString& ErrorString);
|
||||
|
||||
/** Meme filet pour un voyage qui echoue en route. */
|
||||
void HandleTravelFailure(UWorld* World, ETravelFailure::Type FailureType, const FString& ErrorString);
|
||||
|
||||
/**
|
||||
* Ferme la session en cours et rouvre le menu principal.
|
||||
*
|
||||
* La map du menu n'est PAS une propriete de plus : c'est deja la
|
||||
* GameDefaultMap du projet. En dupliquer le chemin ici donnerait deux
|
||||
* valeurs a tenir en phase, et celle-ci ne serait jamais testee.
|
||||
*/
|
||||
void ReturnToMainMenu();
|
||||
|
||||
/**
|
||||
* Une map va etre chargee : on coupe le rendu jusqu'a ce qu'un controller
|
||||
* soit pret.
|
||||
*
|
||||
* PreLoadMap et surtout PAS PostLoadMapWithWorld : ce dernier est diffuse
|
||||
* APRES le BeginPlay des acteurs. Sur une map chargee localement -- le menu,
|
||||
* ou la partie chez l'hote -- le controller rendait donc la main au rendu,
|
||||
* et on la lui reprenait juste apres. Ecran noir definitif, jusqu'au filet
|
||||
* de securite. Chez un client ca passait par accident, son controller
|
||||
* arrivant plus tard.
|
||||
*/
|
||||
void HandlePreLoadMap(const FString& MapName);
|
||||
|
||||
void SetWorldRenderingSuspended(bool bSuspended);
|
||||
|
||||
/** Une image de chauffe vient de passer : on decompte, ou on rappelle. */
|
||||
void TickSceneWarmup();
|
||||
|
||||
/** Images restantes a rendre avant d'eclaircir. */
|
||||
int32 RemainingWarmupFrames = 0;
|
||||
|
||||
/** Debut de la chauffe, pour appliquer le plafond en secondes. */
|
||||
double WarmupStartTime = 0.0;
|
||||
|
||||
/** Ce qu'on fait une fois la chauffe finie -- eclaircir, cote appelant. */
|
||||
FSimpleDelegate SceneWarmupCompleted;
|
||||
|
||||
FDelegateHandle NetworkFailureHandle;
|
||||
FDelegateHandle TravelFailureHandle;
|
||||
FDelegateHandle PreLoadMapHandle;
|
||||
|
||||
/**
|
||||
* Filet : si aucun controller ne rend la main -- connexion qui n'aboutit
|
||||
* pas, spawn rate -- on rallume quand meme. Un ecran noir definitif se lit
|
||||
* comme un plantage, et c'est pire que le defaut qu'on corrige.
|
||||
*/
|
||||
FTimerHandle RenderingResumeTimeout;
|
||||
|
||||
/** Un retour au menu est deja en cours, voulu ou non. */
|
||||
bool bReturningToMainMenu = false;
|
||||
|
||||
/**
|
||||
* Stocke un NOM et pas un index : les index changent des qu'on ajoute ou
|
||||
* supprime une camera dans la map, et on retomberait sur autre chose.
|
||||
|
||||
Reference in New Issue
Block a user