Zmiana sceny- portal przejścia.
Temat jest kontynuacją kodu z poprzedniego tematu (zobacz). Do już istniejących skryptów dojdą skrypty pozwalające zmienić scenę z bieżącej na nową z wykorzystaniem modelu przejścia poprzez portal. Niezależnie od sposobu wywołania nowej sceny używa się instrukcji o postaci
Wskazówka:
Application.LoadLevel(nazwaNowejSceny);
Przykład omówiony w tym temacie wczytuje nową scenę przez wykorzystanie metod OnTriggerEnter(), OnTriggerStay(), OnTriggerExit().
Poniższy film pokazuje uzyskany efekt (kliknij na obrazku aby obejrzeć)
Przygotowanie scen
W projekcie przygotowujemy dwie lub więcej scen. Każdej ze scen nadajemy inną nazwę.
Każdą z nowo utworzonej sceny dodajemy do listy kompilacji scen (opcja Menu/ File/ Build Settings)
UWAGA! W nowo utworzonych scenach usuwamy standardowo dodawaną kamerę.
W przedstawionym rozwiązaniu gracz, przechodząc ze sceny do nowej sceny, zabiera ze sobą skonfigurowaną kamerę i komponent Cinemachine.
Przechodzimy na scenę główną (u mnie to Scena1) i przenosimy główną kamerę oraz komponent Cinemachine (FreeLook Camera) do obiektu postaci gracza (u mnie obiekt o nazwie dzikus).
Obiektowi postaci gracza przypisujemy tag o nazwie Player
Skrypt blokujący usuwanie obiektu podczas przejścia
Aby obiekt nie był od nowa tworzony z każdym ładowaniem sceny, blokujemy jego usunięcie. Jednocześnie w skrypcie dodamy zmienne związane z przejściem. Tworzymy nowy skrypt o nazwie Instancja. Zawartość skryptu jest bardzo prosta (patrz na poniższy kod)
Wskazówka:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Instancja : MonoBehaviour
{
//skrypt zachowujący kazdy obiekt przy przejsciu z jednej sceny do drugiej
public static Instancja instancja;
//nazwa tagu portalu przejścia z jednej sceny do innej
public static string tagPortal;
//zaznacz ze gracz się nie teleportował
public static bool fTeleportacja=false;
private void Awake()
{
if (!instancja)
{
DontDestroyOnLoad(this.gameObject);
instancja = this;
}
else
{
Destroy(this.gameObject);
}
}
}
Skrypt podpinamy do obiektu postaci gracza.
Portal przejścia
Idea portalu przejścia z jednej sceny do drugiej opiera się na wykorzystaniu komponentu Box Collider z włączoną opcją wyzwalacza kolizji (Is Trigger).
Kolizje obsłużymy w skrypcie.
Tworzenie portalu, zaczniemy od przygotowania siatek w Blenderze. Tworzymy siatkę budowli portalu (u mnie kamienny łuk) oraz siatkę lustra wody. Kolizja z lustrem będzie powodować przejście. Siatki eksportujemy jako plik *.fbx i importujemy w Unity. Tworzymy prefabrykat portalu.
Do siatki kamiennego łuku dodajemy komponent Mesh Collider
Do siatki lustra przejścia dodajemy komponent Box Collider, ustawiamy opcję Is Trigger na true.
Do lustra przejścia podpinamy skrypt o nazwie Portal(). Skrypt ten tworzymy i wprowadzamy poniższy kod
Wskazówka:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Portal : MonoBehaviour
{
[SerializeField] private String nazwaScenyCelu;
[SerializeField] private String tagPortaluCelu=null;
[SerializeField] private bool fGraczJestNaScenie = false;
//gdy gracz wszedl do portalu
private void OnTriggerEnter(Collider other)
{
Instancja.tagPortal = tagPortaluCelu;
}
//gdy gracz jest wewnatrz portalu
private void OnTriggerStay(Collider other)
{
//ni ebyło teleportacji to sie teleportuj
if(!Instancja.fTeleportacja)
{
Application.LoadLevel(nazwaScenyCelu);
//zaznacz ze gracz się teleportował
Instancja.fTeleportacja = true;
}
}
//gdy gracz zrezygnował z portalu
private void OnTriggerExit(Collider other)
{
Instancja.tagPortal = null;
//zaznacz ze gracz się nie teleportował
Instancja.fTeleportacja = false;
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void FixedUpdate()
{
if (!fGraczJestNaScenie)
{
//odszukaj obiekt gracza
GameObject g = GameObject.FindGameObjectWithTag("Player");
//gracz wszedł na scenę
if (g != null)
{
GameObject portalCelu=null;
if(Instancja.tagPortal!=null)portalCelu = GameObject.FindGameObjectWithTag(Instancja.tagPortal);
//ustaw gracza po przejsciu we współrzednych portalu
if (portalCelu != null)
{
g.GetComponent<Transform>().position =
new Vector3(portalCelu.transform.position.x,
portalCelu.transform.position.y,
portalCelu.transform.position.z);
}
fGraczJestNaScenie = true;
}
}
}
}
Z tak przygotowanego obiektu portalu tworzymy prefabrykat.
Osadzamy portale w scenach
Użycie portali na scenach wymaga dodania do projektu kilku tagów dla nazw portali.
Na jednej scenie może być dowolna ilość portali, ale każdy z portali tej sceny musi mieć inny przypisany tag (patrz punkt 2 na poniższym rysunku). Dane dla lustra przejścia mogą się w osadzonych portalach powtarzać.
Procedurę osadzania i przypisania danych przejść powtarzamy dla każdej sceny
Sceny mamy gotowe. Uruchom projekt, startując ze sceny głównej i sprawdź, jak zachowuje się postać obiektu gracza.
Zauważ, że na przykład przy zabraniu oszczepu, postać przechodzi przez portal wraz z oszczepem tak jak i kamerą. Rozwiązanie blokowania niszczenia obiektu, działa i na dzieci podpięte do obiektu głównego.