Search Unity

Relative Position for Changing 2D Graphics in 3D Environment

Discussion in 'Scripting' started by jakejolli, Mar 4, 2015.

  1. jakejolli

    jakejolli

    Joined:
    Mar 22, 2014
    Posts:
    54
    My game uses Sprites for enemies in 3D space, similar to early 3D games like Doom or Daggerfall.

    Because the graphics are 2D, they must always face the player to be visible, but I need to know the enemy's position relative to the player, and the direction which the enemy is facing (not the graphic, but the enemy).

    I know the facing direction is confusing, since the enemy's graphic is always facing the player. But the 'facing direction' I'm referring to for the enemy (not the graphic), will be used in conjunction with the direction relative to the player to determine which graphic to display, i.e:

    .

    Just to reiterate, the GRAPHIC always faces the player, but in the code, the enemy has a seperate value for facing direction.

    I've used the following code to determine the enemy's position based on 8 compass points (N, NE, E, SE, S, SW, W, NW) in relation to the player:

    Code (CSharp):
    1. public Vector3 playerPos;
    2.     public Vector3 posRelativeToPlayer;
    3.     public enum facingDirs{
    4.         N, NW, W, SW, S, SE, E, NE
    5.     }
    6.  
    7.     public facingDirs facingDirection;
    8.     public facingDirs dirRelativeToPlayer;
    9.     public float xDist;
    10.     public float zDist;
    11.     public float distQuotient;
    12.    
    13.     // Update is called once per frame
    14.     void Update () {
    15.         playerPos = GameObject.Find ("First Person Controller").transform.position;
    16.         posRelativeToPlayer = transform.position - playerPos;
    17.         zDist = posRelativeToPlayer.z;
    18.         xDist = posRelativeToPlayer.x;
    19.         distQuotient = xDist / zDist;
    20.         //Debug.Log (distQuotient);
    21.  
    22.         if (playerPos.z > this.transform.position.z){
    23.             if (distQuotient < -2){
    24.                 dirRelativeToPlayer = facingDirs.W;
    25.             } else if (distQuotient > -2 && distQuotient < -0.5) {
    26.                 dirRelativeToPlayer = facingDirs.NW;
    27.             } else if (distQuotient > -0.5 && distQuotient < 0.5) {
    28.                 dirRelativeToPlayer = facingDirs.N;
    29.             } else if (distQuotient > 0.5 && distQuotient < 2) {
    30.                 dirRelativeToPlayer = facingDirs.NE;
    31.             } else if (distQuotient > 2) {
    32.                 dirRelativeToPlayer = facingDirs.E;
    33.             }
    34.         } else {
    35.             if (distQuotient < -2){
    36.                 dirRelativeToPlayer = facingDirs.E;
    37.             } else if (distQuotient > -2 && distQuotient < -0.5) {
    38.                 dirRelativeToPlayer = facingDirs.SE;
    39.             } else if (distQuotient > -0.5 && distQuotient < 0.5) {
    40.                 dirRelativeToPlayer = facingDirs.S;
    41.             } else if (distQuotient > 0.5 && distQuotient < 2) {
    42.                 dirRelativeToPlayer = facingDirs.SW;
    43.             } else if (distQuotient > 2) {
    44.                 dirRelativeToPlayer = facingDirs.W;
    45.             }
    46.         }
    The code above works for determining relative direction.

    I have two questions:

    1) The if else/if above seems clunky and inefficient. Is there a different way to accomplish this (other than switches)?

    2) And this is the main question... Can I change the graphic based on dirRelativeToPlayer and facingDirection other than:

    Code (CSharp):
    1. if(facingDirection == facingDirs.N){
    2.      if(dirRelativeToPlayer == facingDirs.E){
    3.           enemy.graphic = rightGraphic; //This is pseudocode
    4.      } else (otherCondition){
    5.          ...
    6.      }
    7. } else if (otherCondition){
    8. ....
    9. }
    Thanks in advance.
     
  2. jakejolli

    jakejolli

    Joined:
    Mar 22, 2014
    Posts:
    54
    In case anyone was wondering, I found a way around if/else-ing by doing some funny math with my graphics array:

    Code (CSharp):
    1. public class MultiDirGraphicsTemp : MonoBehaviour {
    2.  
    3.     public Vector3 playerPos;
    4.     public Vector3 posRelativeToPlayer;
    5.     public enum facingDirs{
    6.         N, NW, W, SW, S, SE, E, NE
    7.     }
    8.  
    9.     public facingDirs facingDirection;
    10.     public facingDirs dirRelativeToPlayer;
    11.     public float xDist;
    12.     public float zDist;
    13.     public float distQuotient;
    14.     public Sprite[] graphics = new Sprite[7];
    15.  
    16.     void Update () {
    17.  
    18.         playerPos = GameObject.Find ("First Person Controller").transform.position;
    19.         posRelativeToPlayer = transform.position - playerPos;
    20.         zDist = posRelativeToPlayer.z;
    21.         xDist = posRelativeToPlayer.x;
    22.         distQuotient = xDist / zDist;
    23.  
    24.         //Still can't think of a better way to do this:
    25.         if (playerPos.z > this.transform.position.z){
    26.             if (distQuotient < -2){
    27.                 dirRelativeToPlayer = facingDirs.E;
    28.             } else if (distQuotient > -2 && distQuotient < -0.5) {
    29.                 dirRelativeToPlayer = facingDirs.SE;
    30.             } else if (distQuotient > -0.5 && distQuotient < 0.5) {
    31.                 dirRelativeToPlayer = facingDirs.S;
    32.             } else if (distQuotient > 0.5 && distQuotient < 2) {
    33.                 dirRelativeToPlayer = facingDirs.SW;
    34.             } else if (distQuotient > 2) {
    35.                 dirRelativeToPlayer = facingDirs.W;
    36.             }
    37.         } else {
    38.             if (distQuotient < -2){
    39.                 dirRelativeToPlayer = facingDirs.W;
    40.             } else if (distQuotient > -2 && distQuotient < -0.5) {
    41.                 dirRelativeToPlayer = facingDirs.NW;
    42.             } else if (distQuotient > -0.5 && distQuotient < 0.5) {
    43.                 dirRelativeToPlayer = facingDirs.N;
    44.             } else if (distQuotient > 0.5 && distQuotient < 2) {
    45.                 dirRelativeToPlayer = facingDirs.NE;
    46.             } else if (distQuotient > 2) {
    47.                 dirRelativeToPlayer = facingDirs.E;
    48.             }
    49.         }
    50.  
    51.         int dirSum;
    52.  
    53.         //This kind of treats the array circularly... It wraps around the array so that the element after the last is 0
    54.         //8 is number of elements in graphics array
    55.         if ((int)dirRelativeToPlayer > (int)facingDirection){
    56.             dirSum = 8 - ((int)dirRelativeToPlayer - (int)facingDirection);
    57.         } else {
    58.             dirSum = Mathf.Abs ((int)dirRelativeToPlayer - (int)facingDirection);
    59.         }    
    60.        
    61.          gameObject.GetComponentInChildren<SpriteRenderer>().sprite = graphics[dirSum];
    62.     }
    63. }
     
  3. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    9,408
  4. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    9,408
    ^ actually forgot the facing direction from that.. maybe it would work just by adding current facing angle to that.
     
  5. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    9,408
    JamesArndt likes this.
  6. Deleted User

    Deleted User

    Guest