Trafienie w tarczę strzelniczą

Ten temat porusza jeden z możliwych sposobów ustalenia punktów za trafienie ustalonych na podstawie przechwycenia współrzędnych kolizji pocisku z celem. Krótki film ilustruje uzyskany efekt

Efekt trafienia w tarczę Unity

Przygotowujemy tarczę

Tarczę wykonamy w Blenderze z przypisaną teksturą

Model tarczy strzelniczej Unity

Eksportujemy do pliku *.fbx i importujemy w Unity. Z zaimportowanej tarczy robimy prefabrykat. Dodajemy Mesh Collider. Zaznaczamy opcję Convex i Is Trigger. Patrz poniższy rysunek.

Mesh Collider tarczy strzelniczej Unity

Przez zmianę położenia i ułożenia kamery ustawiamy większy widok na scenę gry (tak aby można było celować w ruchomą tarczę).

tarcza strzelnicza Unity

Przechodzimy do prefabrykatu Kula i przypisujemy Tag o nazwie: kula

tagi w Unity

Skrypt trafienia

Tworzymy skrypt o nazwie TrafienieWTarcze. W edytorze Unity otwieramy edycję prefabrykatu tarczy strzelniczej. Do obiektu Tarcza podpinamy utworzony skrypt. Dodajemy Mesh Collider?a. A w nim ustawiamy opcje Convex i Is Trigger na wybrane. Patrz poniższy rysunek.

skrypt trafienia w cel w Unity

Nadpisujemy metodę OnTriggerEnter(). Do testów wprowadzamy informację wykrycia współrzędnych kolizji trafienia kuli w tarczę. Bieżąca postać skryptu poniżej.

Wskazówka:


using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

public class TrafienieWTarcze : MonoBehaviour
{
    void OnTriggerEnter(Collider o)
    {
        if (o.tag == "kula")
        {
            //pokaż w debugerze współzredne uderzenia pocisku
            Debug.Log(o.ClosestPoint(transform.position).ToString());
        }
    }
    void Start()
    {
    }
    // Update is called once per frame
    void Update()
    {
    }
}

Dla ułatwienia testów blokujemy ruch tarczy przez wyłącznie skryptu ruchu. Patrz poniżej.

OnTriggerEnter w Unity

Uruchamiamy scenę. Do tarczy podjeżdżamy działem i strzelamy. W komunikatorze możemy odczytać współrzędne trafienia kuli w cel. Co oznacza, że wykrywanie kolizji działa.

trafienie kuli w cel w Unity

W zależności od rozmiarów naszej tarczy musimy ustalić przedziały granicy odległości od jej środka związane z ilością punktów za trafienie. Ustalenie przedziałów ułatwi użycie pustego obiektu Create Empty przesuwanego myszką w siatce tarczy. Znaczenie mają współrzędne Y, Z. Na ich podstawie obliczymy moduł wektora odległości trafienia od środka tarczy.

granice kolizji celu Unity

W zależności jak jest wyjustowana tekstura tarczy, odczyty w waszych projektów mogą być różne w stosunku do podanych przeze mnie. Kolejne odczyty granic zapisujemy w tablicy wektorów 3D.

Wskazówka:


public class TrafienieWTarcze : MonoBehaviour
{

    private Vector3[] tab = new Vector3[] {
        new Vector3(0.32f,0,0),
        new Vector3(0.32f,0.086f,0.024f),
        new Vector3(0.32f,0.172f,0.049f),
        new Vector3(0.32f,0.358f,0.101f),
        new Vector3(0.32f,0.448f,0.126f),
        new Vector3(0.32f,0.539f,0.151f),
        new Vector3(0.32f,0.628f,0.176f),
        new Vector3(0.32f,0.718f,0.201f),
        new Vector3(0.32f,0.809f,0.226f),
        new Vector3(0.32f,0.897f,0.251f)
    };

Podane współrzędne granic przeliczamy na promienie okręgów, czyli długości wektorów 3D. Przy przeliczeniu musimy uwzględnić skalę osadzonego obiektu tarczy w świecie 3D. Do skryptu dodamy tablicę na granice. Przeliczenie zrobimy w funkcji Start(). Patrz poniższy kod.

Wskazówka:


    private float[] granica = new float[10];

    void Start()
    {
        //rób granice punktowe obszarów trafień
        for(int i = 0; i < granica.Length; i++)
        {
            granica[i] = new Vector3(0,
                                  tab[i].y * transform.localScale.y,
                                  tab[i].z * transform.localScale.z).magnitude;
            Debug.Log("Granica:" + granica[i].ToString());
        }
        
    }

Modyfikujemy wyzwalacza kolizji

W metodzie wyzwalacza kolizji z przechwyconych współrzędnych trafienia obliczamy odległość od środka tarczy. Porównujemy z tablicą promieni granic i przydzielamy punkty za trafienie. Zmodyfikowany kod wygląda jak poniżej.

Wskazówka:


    void OnTriggerEnter(Collider o)
    {
        if (o.tag == "kula")
        {
            //pokaż w debugerze współzredne uderzenia pocisku
            Debug.Log(o.ClosestPoint(transform.position).ToString());
            Vector3 odleglosc = o.ClosestPoint(transform.position)-transform.position;
            float odl=  new Vector3(0,
                                  odleglosc.y,
                                  odleglosc.z).magnitude;
            //pokaz punkty z indeksu okręgu trafienia
            //0 to 10,1 to 9, itd...
            int pkt = 0;
            for(int i = 0;i < granica.Length; i++)
                if (odl > granica[i]) pkt = granica.Length-i;
            Debug.Log("Punkty trafienia:"+pkt.ToString());
        }
    }

Uruchamiamy scenę i sprawdzamy komunikaty w debugerze. Poniżej ilustracja działającej sceny.

Debug.Log w Unity

Robimy prefabrykaty punktów trafień

W zależności od pomysłowości wizualizację naliczania punktów za trafienie można zrobić w dowolny sposób. Ten pomysł bazuje na siatkach cyfr. Modele przestrzenne cyfr przygotujemy w Blenderze.

siatki cyfr Blender

Przechodzimy do Unity i importujemy siatki cyfr.

prefabrykaty cyfr w Unity

Z zaimportowanych siatek robimy prefabrykaty dla każdej cyfry i jednej liczby (10). Ewentualnie prefabrykat liczby dziesięć może być utworzony z dwóch cyfr 1 i 0. Inicjujemy skrypt ruchu pionowego cyfr .Nadajemy mu nazwę RuchPionowyGora. Skrypt jest prosty. Zawiera dwie zmienne dla współczynników prędkości liniowej i prędkości obrotowej.

Wskazówka:


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

public class RuchPionowyGora : MonoBehaviour
{
    [SerializeField] private float v;
    [SerializeField] private float vObrotu;
    // Update is called once per frame
    void Update()
    {
        //przesuwaj pionowo w górę
        transform.position += Vector3.up * v * Time.deltaTime;
        //obarcaj wokól pionowej osi
        //tu nalezy odbrać oś doświadczalnie ze wzgeldu na układ 
        //orientacji wektorów dla siatki
        //dobierz gdy na scenie bedzie pojawiac się prefabrykat
        transform.Rotate(0,0,vObrotu * Time.deltaTime);
    }
    
}

Skrypt podpinamy do każdego prefabrykatu cyfry. Dobieramy wartości współczynników prędkości według własnego uznania.

ruch prefabrykatu w Unity

Wywołujemy prefabrykaty cyfr w momencie trafienia

Modyfikujemy skrypt TrafienieWTarcze (wcześniej już napisany i podpięty do tarczy) tak aby podczas trafienia został zniszczony pocisk i został utworzony obiekt prefabrykatu cyfry w zależności od zdobytych punktów. Do skryptu dodajemy tablicę na prefabrykaty liczb. Postać skryptu po modyfikacji

Wskazówka:


using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

public class TrafienieWTarcze : MonoBehaviour
{
    [SerializeField]GameObject[] prefabLiczba=new GameObject[10];
    private Vector3[] tab = new Vector3[] {
        new Vector3(0.32f,0,0),
        new Vector3(0.32f,0.086f,0.024f),
        new Vector3(0.32f,0.172f,0.049f),
        new Vector3(0.32f,0.358f,0.101f),
        new Vector3(0.32f,0.448f,0.126f),
        new Vector3(0.32f,0.539f,0.151f),
        new Vector3(0.32f,0.628f,0.176f),
        new Vector3(0.32f,0.718f,0.201f),
        new Vector3(0.32f,0.809f,0.226f),
        new Vector3(0.32f,0.897f,0.251f)
    };
    private float[] granica = new float[10];

    void Start()
    {
        //rób granice punktowe obszarów trafień
        for(int i = 0; i < granica.Length; i++)
        {
            granica[i] = new Vector3(0,
                                  tab[i].y * transform.localScale.y,
                                  tab[i].z * transform.localScale.z).magnitude;
            Debug.Log("Granica:" + granica[i].ToString());
        }
        
    }
    
    void OnTriggerEnter(Collider o)
    {
        if (o.tag == "kula")
        {
            //pokaż w debugerze współzredne uderzenia pocisku
            Debug.Log(o.ClosestPoint(transform.position).ToString());
            Vector3 odleglosc = o.ClosestPoint(transform.position)-transform.position;
            float odl=  new Vector3(0,
                                  odleglosc.y,
                                  odleglosc.z).magnitude;
            //pokaz punkty z indeksu okręgu trafienia
            //0 to 10,1 to 9, itd...
            int pkt = 0;
            for(int i = 0;i < granica.Length; i++)
                if (odl > granica[i]) pkt = granica.Length-i;
            //rob prefabrykat liczby
            GameObject p = Instantiate(prefabLiczba[pkt-1],
                           o.ClosestPoint(transform.position),
                           Quaternion.Euler(-90, 0, 0));
            //Ustaw czas zycia liczby na 2.5 sekundy
            Destroy(p, 2.5f);
            //zniszcz kule
            Destroy(o.gameObject);
        }
    }
}

Prefabrykaty liczb podłączamy do skrypt. Patrz poniższy rysunek.

prefabrykaty cyfr w Unity

Uruchamiamy scenę i sprawdzamy efekt działania. Patrz poniższy rysunek.

efekt trafienia w tarczę w Unity

Przy trafieniu w tarczę pocisk jest niszczony. Pojawia się eksplozja i liczba punktów trafienia.

Alkomat- wirtualny test

Alkomat- darmowa aplikacja na Androida

Pobierz ze sklepu Google Play
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