Programowanie obiektów fbx
Zaimportowane modele 3D w postaci siatek przygotowanych w zewnętrznym edytorze grafiki 3D na przykład programie Blender staja się obiektami możliwymi do oprogramowania (tak jak standardowe obiekty dostępne w Unity) po dodaniu do sceny. Owszem nie będę posiadać colliderów i innych komponentów za wyjątkiem właściwości transformacji- pozycja, rotacja, skala. Poniższy temat będzie dotyczyć przygotowania sceny z siatkami modeli zaimportowanych z plików fbx.
Cel: Utwórz scenę z siatką gruntu, działa, którym można się poruszać i strzelać pod dowolnym kątem i w dowolnym kierunku
Zaimportuj plik *.fbx z siatkami modeli
Czynności zostały opisane w tym temacie otwórz. Pobierz i zaimportuj siatki z pliku dzialoStrzal.zip. Prawidłowo wykonany import przedstawi poniższa ilustracja
Zbuduj scenę
Na scenie osadź grunt i przypisz parametry transformacji. Wektor pozycji (0,0,0), wektor rotacji (-90,0,0), wektor skali (50,50,1). Patrz poniższa ilustracja
Do sceny dodaj pusty obiekt 3D (Create Empty) i nadaj mu nazwe: dzialo. W zakładce hierarchii obiektów do dodanego przed chwilą obiektu 3D przeciągnij myszką modele siatek fbx lawety i lufy. Patrz poniższy rysunek
Powstała nam obiekt dzialo (rodzic), który nie ma siatki 3D, ale posiada dwa obiekty podrzędne z siatkami lawety i lufy. Do rodzica przypisz collidera i komponent ciała fizycznego Rigidbody
Rozmiar collidera odpowiednio zmień używając trybu edycji colliderów. Patrz powyższa ilustracja- punkt 4 (Edit Collider). Skompiluj program i sprawdź efekt działania.
Zauważysz, że działo zapada się w grunt- spada
Dzieje się tak, gdyż grunt nie ma możliwości kolizji z żadnym obiektem sceny. Jest tylko siatką z teksturą. Aby była kolizja należy dodać komponent kolizji siatki (Mesh Collider). Patrz poniższa ilustracja
Uruchom scenę. Teraz działo zatrzymuje się na gruncie.
Piszemy skrypt ruchu działa
Poruszanie działem zorganizujemy z podziałem jazda przód/ tył, obrót lewo/ prawo, podniesienie lufy góra/ dół. Na ruch działa i obrót przeznaczymy klawisze strzałek, podniesienie ludy to klawisze w/s.
W skrypcie użyjemy instrukcji Input.GetAxis("Horizontal") dla obrotu lewo/ prawo oraz instrukcji Input.GetAxis("Vertical") dla jazdy przód/ tył. Instrukcje te wykrywają wciśnięcie klawiszy strzałek jaki i klawiszy W, A, S, D.
Na przykład instrukcja Input.GetAxis("Vertical") przechwytuje użycie klawisza strzałka w górę, strzałka w dół, klawisz W, S. Stworzy to problem obsługi jazdy w przód/ tył i podnoszenia góra/ dół lufy. Aby problem usunąć należy zmienić zbiór przypisanych klawiszy reagujących na instrukcję Input.GetAxis("Vertical").
Wybierz menu Edit/ Project Settings/ Input Manager/ Vertical. W oknie dialogowym ustawień projektu wyczyść pola Alt Negativ Button oraz Alt Positive Button. Patrz poniższy rysunek
Utwórz folder o nazwie Skrypty. Otwórz utworzony folder i dodaj w nim skrypt C# o nazwie Dzialo
Zawartość skryptu
W utworzonym skrypcie tak zainicjujemy zmienne aby można było je zmieniać w edytorze Unity. Zmienne udostępnione do edytora to współczynniki prędkości ruchu i obrotu oraz zmienna na obiekt lufy.
Kod skryptu
Wskazówka:
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using UnityEngine;
public class Dzialo : MonoBehaviour
{
[SerializeField] private GameObject lufa;
[Header("Opcje")]
[Range(0.0f, 10.0f)]
[SerializeField]
private float vRuchu = 2.0f;
[Range(10.0f, 50.0f)]
[SerializeField]
private float vObrotu = 10.0f;
void Ruch()
{
//obrót lewo, prawo
if (Input.GetAxis("Horizontal")!=0)
transform.Rotate(0, Input.GetAxis("Horizontal") * vObrotu * Time.deltaTime, 0);
//jazda przód,tył
if (Input.GetAxis("Vertical") != 0)
transform.position +=Input.GetAxis("Vertical") * transform.forward * vRuchu * Time.deltaTime;
//podnies lufe
if(Input.GetKey(KeyCode.W))
lufa.transform.Rotate(-vObrotu * Time.deltaTime, 0, 0);
//opuść lufe
if (Input.GetKey(KeyCode.S))
lufa.transform.Rotate(vObrotu * Time.deltaTime, 0, 0);
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
Ruch();
}
}
Podepnij skrypt do działa (przeciągnij myszką) i ustaw wartości. Obiekt Lufa przeciągasz myszką do pola Lufa w podpiętym skrypcie.
Uruchom scenę i sprawdź efekt działania. Działo powinno jeździć z możliwością obrotów i podnoszeniem lufy. Patrz poniższa ilustracja.
Granica kątowa podniesienia i opuszczenia lufy
Do skryptu wprowadzimy nową zmienną o nazwie kat typu float. Zmienna będzie przechowywać wartość kąta mierzona względem osi obrotu X
Wskazówka:
public class Dzialo : MonoBehaviour
{
[SerializeField] private GameObject lufa;
[Header("Opcje")]
[Range(0.0f, 10.0f)]
[SerializeField]
private float vRuchu = 2.0f;
[Range(10.0f, 50.0f)]
[SerializeField]
private float vObrotu = 10.0f;
[SerializeField]
private float kat = 0.0f;
Granice zmiany kąta ustalimy funkcją Mathf.Clamp(). Transformację podniesienia lufy wykonamy metodą transform.localEulerAngles. Poniżej zawartość skryptu po zmianach.
Wskazówka:
void Ruch()
{
//obrót lewo, prawo
if (Input.GetAxis("Horizontal")!=0)
transform.Rotate(0, Input.GetAxis("Horizontal") * vObrotu * Time.deltaTime, 0);
//jazda przód,tył
if (Input.GetAxis("Vertical") != 0)
transform.position +=Input.GetAxis("Vertical") * transform.forward * vRuchu * Time.deltaTime;
//podnies lufe
if (Input.GetKey(KeyCode.W))
kat-=vObrotu * Time.deltaTime;
//opuść lufe
if (Input.GetKey(KeyCode.S))
kat+= vObrotu * Time.deltaTime;
kat=Mathf.Clamp(kat, -60.0f, 30.0f);
lufa.transform.localEulerAngles = new Vector3(kat,
lufa.transform.localEulerAngles.y,
lufa.transform.localEulerAngles.z);
}
Uruchom scenę i sprawdź jak zachowuje się lufa po zmianach w kodzie skryptu.
Ruch kamery
Ruch kamery śledzącej poruszający obiekt zrobimy na podobnych zasadach jak w temacie https://www.afizyka.pl/unity-kamera. Różnica będzie taka, że skrypt będzie podpięty do kamery. Wektor odległości śledzenia ruchu obiektu zostanie obliczony z ustawień pary obiektów kamera- śledzony obiekt na scenie.
Utwórz nowy skrypt i nazwij go Kamera. Wypełnij poniższym kodem
Wskazówka:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Kamera : MonoBehaviour
{
[SerializeField] private GameObject obserwowanyObiekt;
private Vector3 odleglosc;
// Start is called before the first frame update
void Start()
{
odleglosc = transform.position
- obserwowanyObiekt.transform.position;
}
// Update is called once per frame
void Update()
{
transform.LookAt(obserwowanyObiekt.transform.position);
transform.position = Vector3.Lerp(
transform.position,
obserwowanyObiekt.transform.position + odleglosc,
0.05f
);
}
}
Skrypt podepnij do kamery. Do podpiętego skryptu przeciągnij obiekt działa. Patrz poniższa ilustracja
Uruchom scenę i sprawdź działanie.
Przy ruchu działa kamera będzie podążać za obserwowanym obiektem