Kamera- podstawowe właściwości

Do materiału z poprzedniego tematu (przejdź do poprzedniego tematu) dodamy obsługę kamery. Zadaniem kamery będzie podążanie za ruchem wybranego obiektu (kapsuły lub kuli). Skrypt obsługi kamery może być podpięty bezpośrednio do kamery lub do utworzonego prostego silnika naszej sceny. W tym temacie wybieramy drugie rozwiązanie.

Tworzymy skrypt obsługi kamery

Dodajemy nowy skrypt o nazwie Kamera.cs i podpinamy go do obiektu Silnik

Main Camera Unity

Skrypt Kamera.cs wypełniamy poniższym kodem

Wskazówka:


using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Kamera : MonoBehaviour
{
    [SerializeField] private Camera kamera;
    private GameObject obserwowanyObiekt=null;

    public GameObject ObserwowanyObiekt
    {
        set { obserwowanyObiekt=value; }
    }
    private void Obserwuj()
    {
        if (obserwowanyObiekt == null) return;
        kamera.transform.position = obserwowanyObiekt.transform.position;
        Debug.Log(obserwowanyObiekt.name);
    }
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        Obserwuj();
    }
}

Stosując metodę set prześlemy wybór aktywnego obiektu za którym ma podążać kamera. Przechodzimy do skryptu Ruch.cs i wprowadzamy zmiany w funkcji aktywnyObiekt(). Patrz poniższy kod

Wskazówka:


void aktywnyObiekt()
{
	if (Input.GetKeyUp(KeyCode.Alpha1))
	{
		aktywny = kapsula;
		GetComponent<Kamera>().ObserwowanyObiekt= aktywny;
		return;
	}
	if (Input.GetKeyUp(KeyCode.Alpha2))
	{
		aktywny = kula;
		GetComponent<Kamera>().ObserwowanyObiekt = aktywny;
		return;
	}
}

Oraz zmiana w funkcji Start()

Wskazówka:


// Start is called before the first frame update
void Start()
{
	aktywny = kapsula;
	GetComponent<Kamera>().ObserwowanyObiekt = aktywny;
}

To podejście zaoszczędzi nam instrukcji przechwytywania wyboru aktywnego obiektu.

Postać funkcji śledzącej obiekt jest na tę chwile bardzo prosta. Kamera przejmuje współrzędne śledzonego obiektu.

Wskazówka:


private void Obserwuj()
{
	if (obserwowanyObiekt == null) return;
	kamera.transform.position = obserwowanyObiekt.transform.position;
	Debug.Log(obserwowanyObiekt.name);
}

Podpinamy główną kamerę sceny

kamera główna Unity

Skompiluj program i sprawdź efekt działania. Widok nie jest zbyt atrakcyjny ale zaobserwujemy ruch kamery. Poniższa ilustracja pokazuje współrzędne zamocowania kamery (patrz kapsuła) oraz podgląd widoku z kamery (okno Main Camera)

Main Camera

Bardziej atrakcyjnym widokiem jest oddalenie kamery od śledzonego obiektu

Wektor odległości kamery

Kamerę oddalimy od obserwowanego obiektu o pewien wektor z przestrzeni trójwymiarowej. W kodzie skryptu Kamera.cs dodajemy zmienną typu Vector3 o nazwie odleglosc

Wskazówka:


public class Kamera : MonoBehaviour
{
    [SerializeField] private Camera kamera;
    [SerializeField] private Vector3 odleglosc;

Zmieniamy funkcję obserwowania obiektu na poniższy kod

Wskazówka:


private void Obserwuj()
{
	if (obserwowanyObiekt == null) return;
	kamera.transform.position = obserwowanyObiekt.transform.position
								+ odleglosc;
	Debug.Log(obserwowanyObiekt.name);
}

Metodą prób ustalamy parametry współrzędnych wektora odległości. Najłatwiej jest to zrobić kompilując program i wtedy dobrać wartości.

transform position Unity

Widok kamery tak ustalony ma pewną wadę. Nie można wycentrować widoku na wskazany obiekt. Możemy to poprawić wykorzystując metodę LookAt klasy Transform. Parametrem tej funkcji współrzędne obserwowanego obiektu. Wprowadzamy kolejna zmianę w kodzie pliku Kamera.cs

Wskazówka:


private void Obserwuj()
{
	if (obserwowanyObiekt == null) return;
	kamera.transform.position = obserwowanyObiekt.transform.position
								+ odleglosc;
	kamera.transform.LookAt(obserwowanyObiekt.transform.position);
	Debug.Log(obserwowanyObiekt.name);
}

Skompiluj program i sprawdź efekt. Zauważysz, że kamera ogniskuje na wybrany aktywny obiekt.

transform.LookAt Main Camera Unity

Widzenie kamery możemy jeszcze poprawić stosując zmianę kąta podniesienia/ skręcenia względem wybranej osi. Do skryptu Kamera.cs dodamy zmienna typu float i przypiszemy jej nazwę katPodniesienia

Wskazówka:


public class Kamera : MonoBehaviour
{
    [SerializeField] private Camera kamera;
    [SerializeField] private Vector3 odleglosc;
    [SerializeField] private float katPodnesienia=0.0f;
W funkcji obserwuj dodamy linijkę kodu z metodą Rotate. Kamerę będziemy obracać względem osi X

Wskazówka:


private void Obserwuj()
{
	if (obserwowanyObiekt == null) return;
	kamera.transform.position = obserwowanyObiekt.transform.position
								+ odleglosc;
	kamera.transform.LookAt(obserwowanyObiekt.transform.position);
	kamera.transform.Rotate(katPodnesienia, 0, 0);
	Debug.Log(obserwowanyObiekt.name);
}

Skompiluj program i przy uruchomionej scenie, zmień i dobierz wartość kąta podniesienia

transform.Rotate Main Camera Unity

Wygładzanie ruchu kamery

Ruch kamery możemy wygładzić z lekkim opóźnieniem za śledzonym celem. W tym celu stosuje się funkcje Lerp z klasy Vector3. Zastosowanie metody płynnego najazdu kamery na obiekt będzie wymagało obliczania nowych współrzędnych kamery w funkcji FixedUpdate(), która wykonywana jest z dużo większą częstotliwością niż Update(). W funkcji Update() wykonamy metodę LookAt i Rotate. Modyfikujemy skrypt Kamera.cs

Wskazówka:


void Update()
{
	//Obserwuj();
	kamera.transform.LookAt(obserwowanyObiekt.transform.position);
	kamera.transform.Rotate(katPodnesienia, 0, 0);
}
private void FixedUpdate()
{
	kamera.transform.position = Vector3.Lerp(
						kamera.transform.position,
						obserwowanyObiekt.transform.position + odleglosc,
						0.01f);
}

Skompiluj program i sprawdź efekt działania. Zauważysz, że kamera zyskała efekt płynnego najazdu na wybrany obiekt.

Pełny kod skryptu Kamera.cs

Wskazówka:


using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Kamera : MonoBehaviour
{
    [SerializeField] private Camera kamera;
    [SerializeField] private Vector3 odleglosc;
    [SerializeField] private float katPodnesienia=0.0f;


    private GameObject obserwowanyObiekt=null;

    public GameObject ObserwowanyObiekt
    {
        set { obserwowanyObiekt=value; }
    }
    private void Obserwuj()
    {
        kamera.transform.position = Vector3.Lerp(
							kamera.transform.position,
							obserwowanyObiekt.transform.position+ odleglosc,
							0.01f);
        kamera.transform.LookAt(obserwowanyObiekt.transform.position);
        kamera.transform.Rotate(katPodnesienia, 0, 0);
    }
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        //Obserwuj();
        kamera.transform.LookAt(obserwowanyObiekt.transform.position);
        kamera.transform.Rotate(katPodnesienia, 0, 0);
    }
    private void FixedUpdate()
    {
        kamera.transform.position = Vector3.Lerp(
						kamera.transform.position,
						obserwowanyObiekt.transform.position + odleglosc,
						0.01f);
    }
}

Pełny kod skryptu Ruch.cs

Wskazówka:


using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Ruch : MonoBehaviour
{
    [SerializeField] private GameObject kapsula, kula;
    //wartość współczynnika predkości
    //i momentu siły
    [SerializeField] private float v = 2.0f,
                                  moment=500.0f;
    private GameObject aktywny;

    
    void aktywnyObiekt()
    {
        if (Input.GetKeyUp(KeyCode.Alpha1))
        {
            aktywny = kapsula;
            GetComponent<Kamera>().ObserwowanyObiekt= aktywny;
            return;
        }
        if (Input.GetKeyUp(KeyCode.Alpha2))
        {
            aktywny = kula;
            GetComponent<Kamera>().ObserwowanyObiekt = aktywny;
            return;
        }
    }

    void ruszaj()
    {
        float kierunek;
        //reaguje na klawisze A,D i strzałki w Lewo, Prawo
        if ((kierunek = Input.GetAxis("Horizontal")) != 0)
        {
            if(aktywny!=kula)
            aktywny.transform.Translate(-kierunek*Time.deltaTime*v,0,0);
            else
            {
                Vector3 momentobrotowy=new Vector3(0, 0, kierunek * Time.deltaTime * moment);
                aktywny.GetComponent<Rigidbody>().AddTorque(momentobrotowy);
            }
        }
        if ((kierunek = Input.GetAxis("Vertical")) != 0)
        {
            if (aktywny != kula)
                aktywny.transform.Translate(0,0,-kierunek * Time.deltaTime * v);
            else
            {
                Vector3 momentobrotowy = new Vector3(kierunek * Time.deltaTime * moment,0,0);
                aktywny.GetComponent<Rigidbody>().AddTorque(momentobrotowy);
            }
        }
    }
    // Start is called before the first frame update
    void Start()
    {
        aktywny = kapsula;
        GetComponent<Kamera>().ObserwowanyObiekt = aktywny;
    }

    // Update is called once per frame
    void Update()
    {
        aktywnyObiekt();
        ruszaj();
    }
}
Układ okresowy- kod qr
Układ okresowy

Układ okresowy pierwiastków- darmowa aplikacja na Androida

Pobierz ze sklepu Google Play
Alkomat- wirtualny test kod qr
Alkomat- wirtualny test

Alkomat- darmowa aplikacja na Androida

Pobierz ze sklepu Google Play
Taklarz- olinowanie stałe kod qr
Olinowanie stałe- kalkulator średnic

Olinowanie stałe- darmowa aplikacja na Androida

Pobierz ze sklepu Google Play
przepis na gogfry

Przepis na gofry

zobacz
przepis na bitą śmietanę

Przepis na bitą śmietanę

zobacz