2015-08-14 12 views
5

Sto lavorando alla creazione di un indicatore nemico Ofscreen utilizzando il tutorial menzionato nel link sottostante. Tuttavia, posso far ruotare l'indicatore per puntare al nemico ma l'indicatore non si sposta da una estremità all'altra dello schermo.Come creare l'indicatore di Ofscreen del nemico in Unity 3D?

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

Questo è il risultato desiderato:

desired-outcome

Fino ad ora sono riuscito a capire il seguito Si prega di aiuto.

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

Puoi spiegare un po 'meglio il tuo problema? Tutto quello che hai ora è "Voglio questo comportamento con questo codice". Cosa sta fallendo esattamente? Qual è la differenza tra l'output desiderato e quello ottenuto? –

+0

@DJ IV DJIV: dove hai aggiunto il codice di cui sopra? Update()? – user1509674

risposta

2

Creare un collisore scatola rettangolare che delimita i confini dello schermo e utilizzare Physics2D.Raycast in direzione del nemico.

Il punto di collisione ti dirà dove deve essere disegnata la freccia verde.

3

Ho fatto un approccio un po 'diverso da quello che tu avevi suggerito, ma senza usare la fisica.

Se "t" è il vostro target, in questo modo è possibile ottenere la sua posizione sullo schermo in pixel (se è fuori dallo schermo si va solo a valori negativi o valori superiore che larghezza)

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

e questa funzione che restituiscono un bool se il Vector3 (in pixel) è sullo schermo

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

la prima cosa che dovremmo fare è controllare se la destinazione è sullo schermo, se non è quindi procedere con il codice.

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

Quindi un semplice calcolo dell'angolo tra il centro dello schermo e il bersaglio.

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; 

La parte successiva del codice determina dove l'oggetto viene confrontato con la telecamera in base all'angolo appena calcolato.

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

Immagine rappresenta quale valore "Edgeline" avrà in base alla posizione di destinazione (rosso rappresenta vista della telecamera) e linee nere divisione dello spazio.

E poi abbiamo questo codice che imposta Trasforma "t2" (indicatore) per correggere la posizione e l'angolo.

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

Sotto abbiamo funzione "intersecano", che il codice è:

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); 
} 

inviamo a questo indice cui funzione la linea di vista della telecamera (rettangolo) abbiamo bisogno di controllare all'incrocio con, e costruire un linea tra il centro dello schermo e la posizione target.

Per una migliore spiegazione di questa funzione sguardo qui: https://www.topcoder.com/community/data-science/data-science-tutorials/geometry-concepts-line-intersection-and-its-applications/

me a valori di A1, B1 e C1 modificato, ciascuno di essi è ora array di 4 ed ogni valore rappresenta il valore necessario per una linea di vista della telecamera (rettangolo).

Se si desidera implementare i margini, è sufficiente modificare il pivot dell'indicatore (posizionare il renderizzatore di sprite effettivo come figlio e spostarlo nello spazio locale come si desidera).

La prossima cosa sarebbe fare questo lavoro per la schiera di obiettivi e mettere tutti quei bersagli in un array dato. Spero che questo aiuti e non essere troppo duro con me, è la mia prima volta che postare qui :)

+0

Grazie, è un lavoro per me. Ma c'è un piccolo bug. Quando targetPosOnScreen.z <0, tutto viene capovolto. Quindi aggiungi questo: – phuongnd

Problemi correlati