Efekt trafienia w cel
Po efekcie odrzutu zrobimy skutek trafienia pocisku w cel w postaci rozerwania celu na kilka części. Bazą tego tematu jest materiał z poprzedniego tematu (zobacz)
Opisany efekt trafienia w pociskiem w cel przedstawia poniższy film
Przygotowanie obiektu celu
Rozerwane części trafionego obiektu należy wcześniej sobie przygotować w postaci nowych siatek wyeksportowanych do pliku *.fbx. Na potrzeby tego tematu przygotowałem obiekt beczki w programie Blender z teksturą narysowaną w programie GIMP.
Beczkę z Blendera eksportujemy do pliku fbx i importujemy w Unity.
Z zaimportowanej beczki tworzymy prefabrykat. Dodajemy ciało fizyczne- Rigidbody. Ustawiamy masę na 50 lub 100 jednostek. Dodajemy collidera w postaci kolizji siatki- Mesh Collider. Zwróć uwagę, że jest zaznaczona opcja Convex (uruchamia zderzacz z innymi siatkami).
Do obiektu przypiszemy unikatowy tag. Według tego tagu pocisk będzie rozróżniać rodzaj trafionego obiektu. Tag należy utworzyć jak poniżej
Tworzymy prefabrykat i usuwamy element beczki ze sceny.
Składowisko beczek
W dowolnym miejscu tworzonego świata 3D osadzamy pusty element (Create Empty). Nadaj mu nazwę (ja nadałem nazwę składBeczek). Ten element posłuży jako rodzić przechowujący kilka beczek dodanych do sceny. Patrz poniższy rysunek.
Scena jest przygotowana. Jeżeli uruchomisz scenę i strzelisz w dowolną beczkę pocisk powinien się od beczki odbić i nic poza tym.
Beczka z odłamkami
Beczkę z odłamkami należy przygotować w Blenderze. Najłatwiej jest zduplikować beczkę i z duplikatu zrobić kilka fragmentów.
Powyższa ilustracja przedstawia pociętą siatkę beczki na trzy fragmenty. Te fragmenty eksportujemy do pliku *.fbx. Importujemy w Unity
Przeciągamy zaimportowane siatki na scenę. Do każdego fragmentu dodajemy właściwość ciała fizycznego (Rigidbody) i Mesh Collidera. Każdemu fragmentowi możemy przypisać różne masy.
Z beczki z odłamkami robimy prefabrykat i usuwamy ze sceny.
Dwukrotnie klikamy myszką w prefabrykat beczki z odłamkami i wchodzimy w edycję prefabrykatu. Tu sprawdzamy czy pozycja i rotacja każdego fragmentu jest równa zero. Patrz poniższy rysunek.
Skrypt eksplozji beczki
Inicjujemy skrypt eksplozji beczki
Zawartość skryptu jest prosta. Skrypt zawiera jedno zewnętrzne pole na prefabrykat beczki z odłamkami. Ze skryptu suwamy funkcję Strat() oraz Update(). Piszemy publiczną funkcję tworzenia prefabrykatu beczki z odłamkami. Poniżej pełna zawartość skryptu
Wskazówka:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EksplozjaBeczki : MonoBehaviour
{
[SerializeField] private GameObject prefabBeczkaOdlamki;
public void RobBeczkeOdlamkow()
{
//utwórz beczkę odłamków z prefabrykatu
GameObject bo = Instantiate(prefabBeczkaOdlamki,
transform.position,
transform.rotation);
//ustaw czas życia odłamków beczki na 10 sekund
Destroy(bo, 10.0f);
}
}
Skrypt podpinamy do prefabrykatu beczki, a w upublicznione pole: Prefab Beczka Odlamki przeciągamy prefabrykat beczki z odłamkami. Patrz poniższa ilustracja
Modyfikacja skryptu eksplozji pocisku
Modyfikujemy skrypt eksplozji pocisku. Ten skrypt utworzyliśmy w poprzednim temacie (zobacz). Obecna jego postać podana jest poniżej. Doszła funkcja ZniszczBeczke() oraz została nadpisana metoda OnCollisionEnter()
Wskazówka:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Eksplozja : MonoBehaviour
{
[SerializeField] private GameObject prefabEksplozja;
[Header("Opcje")]
[Range(1.0f, 10.0f)]
[SerializeField]
private float PromienOdrzutu = 5.0f;
[Range(10.0f, 100.0f)]
[SerializeField]
private float SilaOdrzutu = 20.0f;
private float skladowaSilaPion = 5.0f;
private void ZniszczBeczke(GameObject o)
{
//zrób z trafionej beczki beczkę odłamków
o.GetComponent<EksplozjaBeczki>().RobBeczkeOdlamkow();
//usuń trafioną beczkę
Destroy(o);
//usuń pocisk
Destroy(this.gameObject);
}
private void OnCollisionEnter(Collision o)
{
if (o.gameObject.tag == "beczkaTrucizna")
{
ZniszczBeczke(o.gameObject);
}
}
private void Odrzut()
{
//zrob listę obiektów kolidujacych wewnątrz zadanej sfery
Collider[] kolizje = Physics.OverlapSphere(transform.position, PromienOdrzutu);
foreach (Collider c in kolizje)
{
Rigidbody rb=c.GetComponent<Rigidbody>();
if (rb != null )
rb.AddExplosionForce(SilaOdrzutu,
transform.position,
PromienOdrzutu,
skladowaSilaPion,
ForceMode.Impulse);
}
}
private void OnDestroy()
{
//utwórz obiekt eksplozji
GameObject e = Instantiate(prefabEksplozja,
transform.position,
transform.rotation);
//usuń obiekt eksplozji
Destroy(e, 2.5f);
//włącz odrzut
Odrzut();
}
}
Logika działania skryptu jest prosta, co wynika z zalet programowania obiektowego. Pocisk po trafieniu w dowolnego collidera, sprawdza czy jest to collider beczki. Jeżeli tak, to wywołuje funkcję ZniszczBeczke(). Funkcja robi nowy obiekt beczki z odłamkami na podstawie prefabrykatu. Usuwa trafiona beczkę. Następnie usuwa obiekt właściciela. A podczas niszczenia zostaje utworzona eksplozja, która wytwarza odrzut po wybuchu, co było opisane w poprzednim temacie.
Uruchom scenę i sprawdź działanie.