===== Flere Scener (Levels) =====
{{:images:changing_scene.png|}}
----
==== SceneManager klasse ====
Lav et Area2D med en collision shape der fange når en Player er nået i mål og skal skifte scene.
{{ :ddu:images:scenemanager.png?500 |}}
Tilføj nedenstående script:
using Godot;
using System;
using Godot;
using System.Threading.Tasks;
public partial class SceneManager : CanvasLayer
{
private ColorRect _fadeRect;
private string _nextScene;
private string _spawnPoint;
public override void _Ready()
{
_fadeRect = GetNode("ColorRect");
_fadeRect.Modulate = new Color(0, 0, 0, 0); // transparent
}
public async void ChangeScene(string scenePath, string spawnPoint = "")
{
// Gem hvilken scene vi vil skifte til
_nextScene = scenePath;
// Gem hvilket spawn point player skal starte ved i næste scene
_spawnPoint = spawnPoint;
// Fade skærmen til sort (så spiller ikke ser scene-skift)
await FadeOut();
// Start async load af scene så vi undgår freeze / hakken)
await LoadSceneAsync();
// Selve scene-skiftet // Den gamle scene fjernes og den nye instanseres
GetTree().ChangeSceneToFile(_nextScene);
// Vent 1 frame dette giver Godot tid til at færdiggøre scene-skiftet
// (ellers findes player/node ikke endnu)
await ToSignal(GetTree(), SceneTree.SignalName.ProcessFrame);
// Find player + spawn point i den nye scene
// og sæt player position korrekt
SetPlayerSpawn();
// Fade tilbage fra sort
await FadeIn();
}
private async Task FadeOut()
{
var tween = CreateTween();
tween.TweenProperty(_fadeRect, "modulate:a", 1.0f, 0.3f);
await ToSignal(tween, Tween.SignalName.Finished);
}
private async Task FadeIn()
{
var tween = CreateTween();
tween.TweenProperty(_fadeRect, "modulate:a", 0.0f, 0.3f);
await ToSignal(tween, Tween.SignalName.Finished);
}
private async Task LoadSceneAsync()
{
var loader = ResourceLoader.LoadThreadedRequest(_nextScene);
while (ResourceLoader.LoadThreadedGetStatus(_nextScene) == ResourceLoader.ThreadLoadStatus.InProgress)
{
await ToSignal(GetTree(), SceneTree.SignalName.ProcessFrame);
}
}
private void SetPlayerSpawn()
{
if (_spawnPoint == "") return;
var player = GetTree().GetFirstNodeInGroup("player") as Node2D;
var spawn = GetTree().GetFirstNodeInGroup(_spawnPoint) as Node2D;
if (player != null && spawn != null)
{
player.GlobalPosition = spawn.GlobalPosition;
}
}
}
Scriptet tilføjes som Autoload i Projekt properties, under navnet 'SceneManager'
==== ScenePortal ====
{{ :ddu:images:sceneportal.png?500 |}}
using Godot;
using System;
using Godot;
public partial class ScenePortal : Area2D
{
[Export(PropertyHint.File, "*.tscn")]
public string TargetScene;
[Export] public string TargetSpawnPoint;
public override void _Ready()
{
BodyEntered += OnBodyEntered;
}
private void OnBodyEntered(Node body)
{
if (!body.IsInGroup("player")) return;
// Vi henviser til vores globale(Autoload) SceneManager
GetNode("/root/SceneManager").ChangeScene(TargetScene, TargetSpawnPoint);
}
}
Obs ! når man skifter fra en scene A til en anden scene B, vil den information der var i scene A blive glemt. Har man information så som score, health og andet bør man ikke gemme dette direkte i scenen. Her kan det være en god ide at gemme værdier i en [[:godot_score_global|Global/Autload]].
----