• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Przyciąganie obiektów przez teren w Unity

Object Storage Arubacloud
0 głosów
506 wizyt
pytanie zadane 28 sierpnia 2017 w C# przez Strzechoniusz Nowicjusz (120 p.)
Witam.

Podobny temat był już poruszany, ale wydaje mi się, że potrzebuję czegoś innego. A mianowicie: stworzyłem grę 3D typu RPG. Mam tam teren, obiekty wrogów i obiekty gracza. Wrogowie pojawiają się w losowych miejscach na planszy i poruszają się w stronę gracza. Wrogowie nie latają, nie skaczą, w zamyśle w ogóle nie powinni odrywać się od ziemi. I tutaj się pojawia problem. W skryptach wrogów zaimplementowałem instrukcję, która metodą raycastingu wykrywa gracza lub innego wroga i jeśli takowego wykryje - wróg dalej się nie porusza. Jednak to nie rozwiązuje do końca problemu: jeśli pojawia się dużo wrogów i wszystkie idą do gracza -  pierwszy ładnie się zatrzymuje przed graczem, drugi czasem też, ale częściej jednak korzystając z pędu przesuwa stojącego przed nim wroga minimalnie w stronę gracza i zatrzymuje się i tak dalej. Jeśli w pierwszego wroga uderzy trzech czy czterech następnych ten prawie wchodzi w gracza (w zamyśle zatrzymuje się w odległości 3 jednostki od gracza). I to właściwie nie jest jakieś strasznie złe. Prawdziwym problemem jest to, że jeśli wróg jest dosyć niski, czasem tak jest "wpychany" w gracza, że gracz wchodzi na niego. To psuje efekt. Podobnie dzieje się z samymi wrogami. Jeśli jest cała gromada krasnali, tworzą się z nich małe wieżyczki. Próbowałem już wielu rzeczy żeby to wyeliminować, nic nie działało dostatecznie dobrze. No i wpadł mi do głowy kolejny pomysł, ale nie wiem jak go zrealizować. Chciałbym żeby obiekt gracza i obiekty wrogów były jakby przyczepione do terenu. Chciałbym stworzyc tak silne przyciąganie obiektów przez teraz, żeby mogły poruszać się po terenie (teren jest górzysty, wiele wzniesień, czyli obiekty przesuwają się we wszystkich trzech osiach), ale żadna siła nie jest w stanie ich od tego terenu oderwać w górę. Czy można zrobić coś takiego? Lub może macie inne pomysły które rozwiążą ten problem. Dołączam elementy skryptu, wybaczcie, ale piszę strasznie "brudne" skrypty. Dziękuję za pomoc.

 

using UnityEngine;
using System.Collections;

public class EnemyAIv5 : MonoBehaviour {
   
    public float walkSpeed = 5.0f;
  
    public float runSpeed = 10.0f;
   
    public float attackDistance = 3.0f;
   
    private Transform mojObiekt;
    private Transform gracz;
    private bool patrzNaGracza = false;
    private Vector3 pozycjaGraczaXYZ;
    public float zasiegWzroku = 30f;
    public float zasiegPrzygotowaniaAtaku = 10f;
  
    private bool gladkiObrot = true;
    private float predkoscObrotu = 6.0f;
    

    RaycastHit hit;

    public bool cosFront=false;

   
    public enum stan{s_idzie, s_biegnie, s_walczy, s_nic, s_spawn};

    

   

 

  
    
    void Start () {
        mojObiekt = transform;
        GetComponent<Rigidbody> ().freezeRotation = true;

        if(GameObject.FindWithTag ("Player"))gracz = GameObject.FindWithTag ("Player").transform;

    }

  
    void Update () {

        if(gracz)pozycjaGraczaXYZ = new Vector3 (gracz.position.x, mojObiekt.position.y, gracz.position.z);
        

float dist = Vector3.Distance (mojObiekt.position, gracz.position);

       

        if (dist >= 100) {
            Destroy (gameObject);

        }

        if (HP > 0) {
            if (aktualnyStan != stan.s_spawn) {

                cosFront = false;
                if (Physics.Raycast (transform.position, transform.forward, out hit, (float)(gameObject.GetComponent<BoxCollider>().size.z))) {
                    if (hit.collider.tag == "Enemy") {
                        cosFront = true;
                    }
                }

                if (dist <= zasiegWzroku && dist > zasiegPrzygotowaniaAtaku) {
                    if (!atakuje) {
                        float predkoscRuchu = walkSpeed;
                        
                     
                        if (!cosFront) {
                            mojObiekt.position = Vector3.MoveTowards (mojObiekt.position, pozycjaGraczaXYZ, predkoscRuchu * Time.deltaTime);
                            gameObject.GetComponent<Rigidbody> ().constraints = RigidbodyConstraints.None;
                            GetComponent<Rigidbody> ().freezeRotation = true;

                        } else {
                            gameObject.GetComponent<Rigidbody> ().constraints = RigidbodyConstraints.FreezePosition;
                        }
                       
                     

                    }
                   

                } else if (dist <= zasiegPrzygotowaniaAtaku && dist > attackDistance) {
                    if (!atakuje) {
                        float predkoscRuchu = runSpeed;
                       
                        if (!cosFront) {
                            mojObiekt.position = Vector3.MoveTowards (mojObiekt.position, pozycjaGraczaXYZ, predkoscRuchu * Time.deltaTime);
                            gameObject.GetComponent<Rigidbody> ().constraints = RigidbodyConstraints.None;
                            GetComponent<Rigidbody> ().freezeRotation = true;

                        } else {
                            gameObject.GetComponent<Rigidbody> ().constraints = RigidbodyConstraints.FreezeAll;
                        }
                      
                }
            }
        }            
    }
}
 

 

Z kodu usunąłem niepotrzebne elementy, zakładamy, że nie brakuje żadnych nawiasów czy czegoś takiego.
komentarz 29 sierpnia 2017 przez Bartosz Dokurno Użytkownik (980 p.)

Kod dajemy do bloczka code! 

Takiego o, łatwiej to czytać

 

1 odpowiedź

0 głosów
odpowiedź 29 sierpnia 2017 przez piotrsz109 Stary wyjadacz (13,730 p.)

Dodaj dla gracza i wroga collidery i użyj CharacterController. Poza tym powinieneś użyć do tego NavMeshAgent. Kod:

using UnityEngine;
using UnityEngine.Navigation;

public class EnemyAI : MonoBehaviour {
public float zasiegWzroku;
public Transform player;
private NavMeshAgent agent;

void Start(){
player = GameObject.FindGameObjectWithTag("Player").transform;
agent = player.GetComponent<NavMeshAgent>();
}

void Update(){
if(Vector3.Distance(transform.position, player.position) < zasiegWzroku){
agent.SetDestination(player.position);
}
}
}

W NavMeshAgent możesz ustawić odległość w jakiej ma się wróg zatrzymać a także szybkość chodenia. Życie oraz atak sam dopisz.

Podobne pytania

0 głosów
3 odpowiedzi 1,058 wizyt
pytanie zadane 22 listopada 2016 w OpenGL, Unity przez Tom_Ja Dyskutant (7,970 p.)
0 głosów
1 odpowiedź 200 wizyt
0 głosów
0 odpowiedzi 344 wizyt
pytanie zadane 29 lipca 2016 w C# przez natrov Gaduła (3,970 p.)

92,570 zapytań

141,422 odpowiedzi

319,643 komentarzy

61,958 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...