Autor Wątek: Przyciąganie do siatki cube 1x1- źle działający skrypt  (Przeczytany 2478 razy)

Offline BrunonDEV

  • Użytkownik
    • Construgia -- RPG

# Listopad 07, 2014, 16:16:16
Witam. Kiedyś miałem problemy z napisaniem przyciągania do siatki, i jeden Warsztatowicz napisał mi "core" tego skryptu za mnie. :P
Teraz, kiedy jestem już nieco "lepszy" z programowania w Unity, postanowiłem jeszcze raz przeanalizować ten skrypt, zrozumieć go i naprawić, bo nie do końca działał jak powinien - otóż kiedy budowało się do góry - działa, kiedy "na boki" - już nie. Pierwsze dwa punkty się udały, trzeci - nie. Otóż rozumiem skrypt, ale nie rozumiem, czemu nie działa. ;[
Oto ten skrypt:
using UnityEngine;
using System.Collections;

public class Build_N : MonoBehaviour {
public Transform Gracz;
public Transform prefab;
public int w;
public int h;
public Vector3 Grid = new Vector3(1,1,1);

void Start () {
Gracz = transform;
w = Screen.width/2;
h = Screen.height/2;
}

void Update () {
if (Input.GetKeyDown(KeyCode.X)){
Ray ray = camera.ScreenPointToRay ( new Vector3(w,h,0) );
RaycastHit hit;
if (Physics.Raycast (ray, out hit)) {
float Dystans = Vector3.Distance(hit.point, Gracz.transform.position);
if (Dystans >= 1 && Dystans <= 15){
                                        //Core ->
Vector3 Pos = hit.point;
Pos = new Vector3(Mathf.Round(Pos.x/Grid.x)*Grid.x, Mathf.Round(Pos.y/Grid.y)*Grid.y+0.5f, Mathf.Round(Pos.z/Grid.z)*Grid.z);
Instantiate(prefab, Pos, Quaternion.identity);
                                        //<- Core
Debug.Log(Pos.y);
Debug.Log(hit.point.y);
}
}
}
}
}
Próbowałem już różnych metod i nic. :(
Proszę o pomoc.
« Ostatnia zmiana: Listopad 07, 2014, 16:19:57 wysłana przez BrunonDEV »

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

  • +1
# Listopad 07, 2014, 16:21:27
Przy Y jest +0.5f, przy reszcie nie ma - dodaj do reszty i może zadziała. :)

Offline BrunonDEV

  • Użytkownik
    • Construgia -- RPG

# Listopad 07, 2014, 16:26:52
@up
Próbowałem. ;/
Wtedy przenosi mi obiekt na wszystkich osiach zamiast na tej jednej, na której powinien (np. gdy kliknę na prawą ściankę "x" to powinien mi go przesunąć tylko na osi "x", a nie na wszystkich). ;[

Offline Rethil

  • Użytkownik

  • +2
# Listopad 07, 2014, 19:23:17
Skoro wiesz, że jak klikniesz po prawej to ma ci przenieść coś na +x a jak po lewej to na -x oraz jak klikniesz od góry to ma przenieść na +y a jak od dołu to na -y oraz jak z przodu to na -z a jak z tyłu to na +z, to w czym problem? Dodajesz lub odejmujesz w zależności od tego, w którą ściankę kliknąłeś.

Jeśli chodzi o wykrycie która to ścianka, to musisz się sam zastanowić jak ten problem rozwiązać - gotowe odpowiedzi niczego cię nie nauczą. Pogrzeb w dokumentacji, może zastanów się nad tym problemem w przestrzeni 2d, może rozrysuj to sobie, może będziesz potrzebował dodać jakieś informacje do obiektów - dużo zależy od twojej obecnej implementacji.

Offline BrunonDEV

  • Użytkownik
    • Construgia -- RPG

# Listopad 08, 2014, 09:20:36
Zastanawiałem się, próbowałem sam domyśleć się co to może być oraz szukałem w dokumentacji.
Nic.

@up:
Mógłbyś podać mi chociaż słowo kluczowe do dokumentacji, bo jak na razie, to wpisywałem tam losowe angielskie wyrazy, lub te, które uważałem, że "mogą być odpowiednie".
Przecież pisząc ten temat, szukałem jakiejś odpowiedzi, która pomoże mi rozwiązać problem, lub go rozwiąże, a jak dotąd to dowiedziałem się tylko tego, co wiedziałem.
Ja wracam do dokumentacji, ale jednak miło by było jakby ktoś podsuną mi jakąś funkcję. :P
 
« Ostatnia zmiana: Listopad 08, 2014, 09:22:10 wysłana przez BrunonDEV »

Offline Rethil

  • Użytkownik

  • +1
# Listopad 09, 2014, 12:24:46
W swoim kodzie masz coś takiego
RaycastHit hit;
if (Physics.Raycast (ray, out hit))
Zacząłbym od tego jakie są wywołania funkcji Physics.Raycast i co właściwie uzyskujesz w strukturze RaycastHit

Przecież pisząc ten temat, szukałem jakiejś odpowiedzi, która pomoże mi rozwiązać problem, lub go rozwiąże, a jak dotąd to dowiedziałem się tylko tego, co wiedziałem.

No to też się dziwię, że zadajesz pytanie, bo (jak już wcześniej ci napisałem) masz dobrze zdefiniowany problem, znasz rozwiązanie i brakuje ci tylko implementacji.

Już kiedyś zadałem ci pytanie ile ty właściwie masz lat? Nie z jakiejś złośliwości, ale będąc w pierwszych klasach w szkoły średniej możesz nie znać pewnych pojęć matematycznych, które mogą ci się przydać tutaj. W takim przypadku nakierowywanie cię na nie zamiast je wyjaśnić może wydawać się sadystyczną zabawą pedagogiczną.
« Ostatnia zmiana: Listopad 10, 2014, 14:03:30 wysłana przez Rethil »

Offline BrunonDEV

  • Użytkownik
    • Construgia -- RPG

# Listopad 10, 2014, 16:22:09
@up
Szkoły średniej?
Mam 11 lat i jestem w 5 klasie szkoły podstawowej.
Nie interesuje mnie, że mogę być "za młody" czy coś takiego.

O jakie pojęcia chodzi?

EDIT:
Na tejże stronie:
http://docs.unity3d.com/ScriptReference/RaycastHit.html
nie znalazłem odpowiedzi.
Domyślam się, że chodzi o "collider" albo "transform" albo "point".
« Ostatnia zmiana: Listopad 10, 2014, 16:26:00 wysłana przez BrunonDEV »

Offline Rethil

  • Użytkownik

  • +1
# Listopad 10, 2014, 17:02:06
Mam 11 lat i jestem w 5 klasie szkoły podstawowej.
To dużo wyjaśnia. Postaram się to prosto wytłumaczyć:
O jakie pojęcia chodzi?
(..)
Domyślam się, że chodzi o "collider" albo "transform" albo "point".
Chodzi o takie pojecie jak wektor normalny, którego nie możesz znać, jeśli nie uczysz się matematyki na własną rękę i nie wybiegasz z programem o jakieś 6 lat do przodu (jest on wprowadzany gdzieś w liceum, jeśli w ogóle jest jeszcze w szkole średniej omawiany). W skrócie wskazuje on, w którą stronę jest skierowana powierzchnia (fragment powierzchni)

Ponieważ twoje obiekty to sześciany to sprawa jest dosyć prosta - ściana jest zawsze skierowana w lewo, prawo, górę, dół, do przodu lub do tyłu. Oznacza to, że wektor normalny ścianki wskazuje dokładnie w którą stronę ona jest skierowana.

Raycast to tak jakby wziąć laser i poświecić sobie. Tam gdzie pojawi się czerwona kropka to tam pada promień lasera. Jeśli promień padnie na jakąś ściankę, to musimy poznać jej wektor normalny i dzięki temu będziemy wiedzieć, w którą stronę musimy przesunąć nasz nowy tworzony obiekt.

Na szczęście Unity za nas oblicza wektor normalny w punkcie i możemy go wydostać przez tą zmienną.

Offline mickwa

  • Użytkownik

  • +1
# Listopad 10, 2014, 23:57:29
Zacznę od tego, że jeśli prawdą jest masz 11 lat, to OGROMNY SZACUNEK I SZCZERY PODZIW dla Ciebie za to, że już czytasz dokumentację po Angielsku i programujesz. Gratulacje i powodzenia!

Wracając do Twojego problemu:
Nie jestem pewien co dokładnie masz na myśli przyciąganie do siatki. Czy chodzi o to że jak wciśniesz X to tam gdzie jest akurat kursor ma się pojawić nowy obiekt? (wnioskuję to po tym że jest Instantiate w tym kodzie który wkleiłeś)

Dostawianie sześcianu do trafionej ściany ja zrobiłem tak:
using UnityEngine;
using System.Collections;

public class Build_N : MonoBehaviour
{
    public Transform prefab; // tutaj w Inspektorze wstaw Cube (1,1,1)
    private Camera cam;   
    private Ray ray;
    void Start()
    {
        cam = Camera.main;
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.X))
        {
            ray = cam.ScreenPointToRay(Input.mousePosition);
            Debug.DrawRay(ray.origin, ray.direction * 100, Color.yellow);
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit))
            {
                float x = 0;
                float y = 0;
                float z = 0;
                // sprawdzamy którą ścianę trafiliśmy raycastem na podstawie odległości trafienia od środka trafionego obiektu.
                // Trafiona ściana będzie miała odległość od środka 0.5 lub -0.5 i na tej podstawie wiesz która została trafiona.
                // To zadziała tylko dle szcześcianu o rozmiarze (1,1,1)!! ( Cube )
                if(hit.point.x - hit.transform.position.x == 0.5f)x=1;
                if(hit.point.y - hit.transform.position.y == 0.5f)y=1;
                if (hit.point.z - hit.transform.position.z == 0.5f)z=1;

                if (hit.point.x - hit.transform.position.x == -0.5f) x = -1;
                if (hit.point.y - hit.transform.position.y == -0.5f) y = -1;
                if (hit.point.z - hit.transform.position.z == -0.5f) z = -1;
                // Pozycja dla nowego sześcianu to pozycja trafionego obiektu + przesunięcie w zależności od trafionej ściany
                Vector3 pos = hit.transform.position + new Vector3(x, y, z);
                Instantiate(prefab, pos, Quaternion.identity);
            }
        }
    }
}
Mam nadzieję, że to Ci pomoże.

Offline BrunonDEV

  • Użytkownik
    • Construgia -- RPG

  • +1
# Listopad 12, 2014, 16:43:48
@up:
Wielkie dzięki, bardzo mi to pomogło. :)
Przeanalizowałem dokładnie skrypt i go rozumiem. Po za tym dodałem kilka małych zmian i poprawek.
Działa świetnie!
:)
+
@up-up:
Twoja pomoc również mi się przyda, dowiedziałem się co to jest wektor normalny. :)
+

« Ostatnia zmiana: Listopad 12, 2014, 16:49:13 wysłana przez BrunonDEV »

Offline mickwa

  • Użytkownik

  • +2
# Listopad 12, 2014, 16:56:33
Cieszę się bardzo, jak coś jeszcze potrzeba, pisz :)