Poruszanie obiektów w silniku Unity
Poniższy materiał skupia się na dwóch możliwych przykładach poruszania się obiektów 3D- przesuwanie i toczenie. Przesuwanie zrealizujemy dla kapsuły a toczenie zrealizujemy dla kuli. Skrypt ruchu może być przypisany bezpośrednio do obiektu, który zamierzamy poruszać lub możemy utworzyć silnik zarządzający tworzonym światem. W celach dydaktycznych zastosujemy drugie podejście
Zadania silnika ruchu
- obsłuż wybranie obiektu przy pomocy klawiatury (klawisz 1 to kapsuła, klawisz 2 to kula)
- przesuń wybrany obiekt strzałkami
- dla kapsuły zastosuj translację współrzędnych pozycji przez przesuwanie
- dla kuli zastosuj translację współrzędnych pozycji przez toczenie
Bazą wyjściową dla tego projektu jest utworzony prosty świat 3D w tym temacie Pierwszy program 3D
Tworzenie skryptów w Unity
Przesuń kapsułę i kulę w takie miejsce aby spoczywały na podłodze
Utwórz folder na kody skryptów
W folderze Skrypty zainicjuj skrypt w języku C#. Inicjację rozpoczynasz po kliknięciu prawym przyciskiem myszki w obszarze otwartej zakładki folderu Skrypt i wybierasz z menu prawego przycisku myszki poniższe opcje
Skrypt nazwij Ruch
Do sceny dodaj pusty obiekt (Create Empty), który będzie silnikiem gry.
Pustemu obiektowi przypisz nazwę Silnik, a do inspektora tego obiektu przeciągnij myszką utworzony skrypt (o nazwie Ruch). Prawidłowo wykonane czynności pokazuje poniższa ilustracja.
Podwójnym szybkim kliknięciem w ikonę skryptu rozpocznij jego edycję. Zostaniesz przeniesiony do kompilatora Visual Studio. W kodzie wprowadź dwie prywatne zmienne związane z typem GameObject. Patrz poniższy kod
Wskazówka:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Ruch : MonoBehaviour
{
[SerializeField] private GameObject kapsula, kula;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
Zastosowanie polecenia [SerializeField] udostępnia wybrane zmienne w edytorze Unity. Patrz poniższa ilustracja
Do udostępnionych zmiennych przeciągnij myszką z zakładki aktywnej sceny obiekty Capsule i Sphare
Od tej pory w kodzie skryptu Ruch.cs oba obiekty są dostępne (w tym wszystkie ich właściwości)
Piszemy funkcję odpowiedzialną za ruch ruchu
Poniższy kod zapewnia przechwycenie wciśnięcia klawiszy odpowiedzialnych za ruch w wzdłuż wybranych osi poziomej i pionowej rozumianej tak jak na płaszczyźnie. Zestaw klawisz odpowiedzialnych za tę reakcje może być dla danego projektu sceny zmieniony. Zobacz w ustawieniach Edit/ Project Settings/ Input Manager
Funkcja ruchu na tym etapie wykorzystuje przesunięcie współrzędnych po osiach X i Z
Wskazówka:
void ruszaj()
{
float kierunek;
//reaguje na klawisze A,D i strzałki w Lewo, Prawo
if ((kierunek = Input.GetAxis("Horizontal")) != 0)
{
aktywny.transform.Translate(-kierunek*Time.deltaTime*v,0,0);
}
if ((kierunek = Input.GetAxis("Vertical")) != 0)
{
aktywny.transform.Translate(0,0,-kierunek * Time.deltaTime * v);
}
}
Funkcję wywołamy w metodzie odświeżania sceny (funkcja Update). Dodajemy zmienną aktywny oraz funkcję wyboru obiektu. Dopisz poniższy kod
Wskazówka:
private GameObject aktywny;
void aktywnyObiekt()
{
if (Input.GetKeyUp(KeyCode.Alpha1))
{
aktywny = kapsula;
return;
}
if (Input.GetKeyUp(KeyCode.Alpha2))
{
aktywny = kula;
return;
}
}
Wprowadź poniżesz zmiany w funkcji Start() oraz Update()
Wskazówka:
// Start is called before the first frame update
void Start()
{
aktywny = kapsula;
}
// Update is called once per frame
void Update()
{
aktywnyObiekt();
ruszaj();
}
Skompiluj program i sprawdź efekt działania. Zauważysz, że w pewnych warunkach kapsuła się przewraca. Patrz poniższa ilustracja
Dzieje się tak ponieważ kapsuła ma dołączone właściwości bryły sztywnej (Rigdbody), a podczas kolizji pojawiają się moment sił skręcających bryłę wzdłuż osi X, Y i Z. Tę niedogodność usuwamy w prosty sposób. Blokujemy obrót względem osi X i Z. Pionową oś Y zostawiamy odblokowaną. Patrz układ poniższych ustawień blokowania
Skompiluj program i sprawdź efekt działania.
Zmiana pozycji przez toczenie
Obiekty 3D mające dołączoną właściwość Rigdbody mogą zmienić pozycję z wykorzystaniem fizyki momentów sił. Dokładnie w taki sam sposób ja się uczysz na fizyce przy mechanice bryły sztywnej. Wprowadzimy zmiany w kodzie pozwalające kuli się toczyć. Zaczniemy od zmiany jednolitej czerwonej tekstury na wzorzystą teksturę. Tak tekstura pozwoli zaobserwować obrót bryły w trakcie toczenia.
Dodajemy współczynnik momentu siły
Wskazówka:
//wartość współczynnika predkości
//i momentu siły
[SerializeField] private float v = 2.0f,
moment=500.0f;
private GameObject aktywny;
Zmieniamy ciało funkcji odpowiadającej za ruch obiektów
Wskazówka:
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);
}
}
}
Skompiluj program i sprawdź efekt działania. Przy zmianie zwrotu obracania się kuli można zauważyć efekt poślizgu. Silnik Uniti daje możliwość tworzenia różnych materiałów fizycznych o różnych współczynnikach tarcia czy też sprężystości.
Tworzymy materiał fizyczny dla kuli
Chcemy do kuli dodać materiał fizyczny który spowoduje, że kula będzie się odbijać tak jak piłeczka pingpongowa, a kula będzie wykonana o większym współczynniku tarcia.
Przechodzimy do folderu Assets/ Materialy
W obszarze otwartego folderu Material klikamy prawym przyciskiem myszki i wybieramy z menu prawego przyciska myszki opcję Create/ Phisic Material
Ustawiamy współczynnik tarcia dynamicznego (dynamic friction), współczynnik tarcia statycznego (static friction) i sprężystość (bounciness). Patrz poniższa ilustracja
Utworzony materiał fizyczny podpinamy do kuli- przeciągamy myszką do kolidera kuli (Sphere Collider).
Przejdź do tworzonej sceny i podnieś kulę o kilka jednostek nad płaszczyzną podłogi. Uruchom program i sprawdź efekt działania.
Po uruchomieniu sceny zauważysz, że kula przy upadku kilka razy odbije się od podłogi.
Pełny kod utworzonego skryptu Silnik.cs
Silnik.cs:
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 toczenie(Rigidbody rb,Vector3 momentObrotowy)
{
//dodaj moment obrotowy
rb.AddTorque(momentObrotowy);
}
void aktywnyObiekt()
{
if (Input.GetKeyUp(KeyCode.Alpha1))
{
aktywny = kapsula;
return;
}
if (Input.GetKeyUp(KeyCode.Alpha2))
{
aktywny = kula;
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;
}
// Update is called once per frame
void Update()
{
aktywnyObiekt();
ruszaj();
}
}