2015-08-14 14 views
5

Pracuję nad utworzeniem wskaźnika Wróg wroga, korzystając z samouczka wspomnianego poniżej. Mogę jednak obrócić wskaźnik tak, aby wskazywał na wroga, ale wskaźnik nie przesuwa się od końca do końca ekranu.Jak utworzyć wskaźnik Wroga wroga w Unity 3D?

http://gamedevelopment.tutsplus.com/tutorials/positioning-on-screen-indicators-to-point-to-off-screen-targets--gamedev-6644

Jest to pożądany efekt:

desired-outcome

Do tej pory udało mi się dowiedzieć poniżej Proszę o pomoc.

var screenCenter:Vector3 = new Vector3(0.5, 0.5, 0f); 
    //Note coordinates are translated 
    //Make 00 the centre of the screen instead of bottom left 
    screenpos -= screenCenter; 

    //find angle from center of screen instead of bototom left 
    var angle:float = Mathf.Atan2(screenpos.y, screenpos.x); 
    angle -= 90 * Mathf.Deg2Rad; 

    var cos:float = Mathf.Cos(angle); 
    var sin:float = -Mathf.Cos(angle); 

    screenpos = screenCenter + new Vector3(sin*150, cos*150, 0); 

    //y=mx + b format 
    var m:float = cos/sin; 
    var ScreenBounds:Vector3 = screenCenter;// * 0.9f; 

    //Check up and down first 
    if(cos > 0){ 
     screenpos = new Vector3(ScreenBounds.y/m, ScreenBounds.y, 0); 
    }else{//down 
     screenpos = new Vector3(-ScreenBounds.y/m, -ScreenBounds.y, 0); 
    } 
    //If out of bound then get point on appropriate side 
    if(screenpos.x > ScreenBounds.x){//Out of bound must be on right 
     screenpos = new Vector3(ScreenBounds.x, ScreenBounds.y*m, 0); 
    }else if(screenpos.x < ScreenBounds.x){//Out of bound must be on left 
     screenpos = new Vector3(-ScreenBounds.x, -ScreenBounds.y*m, 0); 
    } 
    //Remove the co ordinate translation 
    screenpos += screenCenter; 
    var DistanceIndicatorRectT = DistanceIndicator.GetComponent(RectTransform); 
    DistanceIndicatorRectT.localPosition = new Vector3(screenpos.x * scrWidth/2, screenpos.y * scrHeight/2, DistanceIndicatorRectT.localPosition.z * screenpos.z); 
    DistanceIndicator.transform.rotation = Quaternion.Euler(0, 0, angle*Mathf.Rad2Deg); 
+1

Czy możesz wyjaśnić swój problem trochę lepiej? Teraz masz tylko "chcę tego zachowania z tym kodem". Co dokładnie się nie udaje? Jaka jest różnica pomiędzy pożądanym a uzyskanym wynikiem? –

+0

@DJ IV DJIV: gdzie dodałeś powyższy fragment kodu? Update()? – user1509674

Odpowiedz

2

Tworzenie Collider pole prostokąta wyznaczające granice ekranu i użyj Physics2D.Raycast w kierunku wroga.

Punkt kolizji powie, gdzie należy narysować zieloną strzałkę.

3

Zrobiłem trochę inne podejście niż ty, co Carlos zaproponował, ale bez użycia fizyki.

Jeśli „t” jest twój cel, w ten sposób można je dostać to stanowisko na ekranie w pikselach (jeśli jest poza ekranem to po prostu idzie do wartości ujemnych lub wartości wyższe niż szerokość)

Vector3 targetPosOnScreen = Camera.main.WorldToScreenPoint (t.position); 

I ta funkcja że powrót bool czy Vector3 (w pikselach) jest na ekranie

bool onScreen(Vector2 input){ 
    return !(input.x > Screen.width || input.x < 0 || input.y > Screen.height || input.y < 0); 
} 

Pierwszą rzeczą jaką należy zrobić, to sprawdzić, czy obiekt znajduje się na ekranie, jeśli nie jest wtedy postępować z kodem.

if (onScreen (targetPosOnScreen)) { 
     //Some code to destroy indicator or make it invisible 
     return; 
    } 

Następnie proste obliczenie kąta między środkiem ekranu a celem.

Vector3 center = new Vector3 (Screen.width/2f, Screen.height/2f, 0); 
float angle = Mathf.Atan2(targetPosOnScreen.y-center.y, targetPosOnScreen.x-center.x) * Mathf.Rad2Deg; 

Następna część kodu określa, gdzie obiekt jest porównywany z kamerą w oparciu o kąt, który właśnie obliczyliśmy.

float coef; 
if (Screen.width > Screen.height) 
    coef = Screen.width/Screen.height; 
else 
    coef = Screen.height/Screen.width; 

float degreeRange = 360f/(coef + 1); 

if(angle < 0) angle = angle + 360; 
int edgeLine; 
if(angle < degreeRange/4f) edgeLine = 0; 
else if (angle < 180 - degreeRange/4f) edgeLine = 1; 
else if (angle < 180 + degreeRange/4f) edgeLine = 2; 
else if (angle < 360 - degreeRange/4f) edgeLine = 3; 
else edgeLine = 0; 

http://s23.postimg.org/ytpm82ad7/Untitled_1.png

Obraz reprezentuje jaką wartość „Edgeline” będą opierały się na pozycji docelowej (czerwona przedstawia widok kamery) i czarne linie podziału przestrzeni.

A następnie mamy ten kod, który ustawia Transform "t2" (wskaźnik), aby skorygować położenie i kąt.

t2.position = Camera.main.ScreenToWorldPoint(intersect(edgeLine, center, targetPosOnScreen)+new Vector3(0,0,10)); 
t2.eulerAngles = new Vector3 (0, 0, angle); 

Poniżej mamy funkcję „przecinają”, który kod jest:

Vector3 intersect(int edgeLine, Vector3 line2point1, Vector3 line2point2){ 
    float[] A1 = {-Screen.height, 0, Screen.height, 0}; 
    float[] B1 = {0, -Screen.width, 0, Screen.width}; 
    float[] C1 = {-Screen.width * Screen.height,-Screen.width * Screen.height,0, 0}; 

    float A2 = line2point2.y - line2point1.y; 
    float B2 = line2point1.x - line2point2.x; 
    float C2 = A2 * line2point1.x + B2 * line2point1.y; 

    float det = A1[edgeLine] * B2 - A2 * B1[edgeLine]; 

    return new Vector3 ((B2 * C1[edgeLine] - B1[edgeLine] * C2)/det, (A1[edgeLine] * C2 - A2 * C1[edgeLine])/det, 0); 
} 

Wysyłamy do tego wskaźnika funkcji, z których linia widzenia kamery (prostokąt) musimy sprawdzić skrzyżowania z, i zbudować linia między środkiem ekranu a pozycją docelową.

Dla lepszego wyjaśnienia tej funkcji zajrzyj tutaj: https://www.topcoder.com/community/data-science/data-science-tutorials/geometry-concepts-line-intersection-and-its-applications/

Właśnie zmodyfikowane wartości A1, B1 i C1, każdy z nich jest teraz tablica 4, a każdy wartości reprezentuje wartość potrzebną do jednej linii widzenia kamery (prostokąt).

Jeśli chcesz zaimplementować marginesy, po prostu zmień oś wskaźnika (ustaw aktualny rendener sprite jako element potomny i przenieś go w przestrzeń lokalną, jak chcesz).

Następnym krokiem byłoby wykonanie tej pracy dla tablicy celów i umieszczenie wszystkich tych celów w danej tablicy. Mam nadzieję, że to pomoże i nie bądź dla mnie zbyt trudny, to mój pierwszy wpis tutaj :)

+0

Dziękuję, to działa dla mnie. Ale jest mały błąd. Kiedy targetPosOnScreen.z <0, wszystko jest odwrócone. Dodaj to: – phuongnd