Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

How to get an index based on camera perspective related to an objects transform in C#

Discussion in 'Scripting' started by Buzzbomb, Jan 17, 2014.

  1. Buzzbomb

    Buzzbomb

    Joined:
    Mar 13, 2013
    Posts:
    8
    I've been having trouble implementing a script to get an eight way index based on where the main camera is and where an object within view is facing.

    My goal is to use billboarding and spritesheet offsetting to achieve the enemy "look" from the classic Doom and Wolfenstien games...(this could reduce the memory footprint DRASTICALLY leaving room for fun mechanics and such! )

    I was hoping to use Atan' angles to show if an object is facing the camera (face to face, front-right, right side, rear right...etc) and also one index for vertical perspectives(same level-left, left above, directly above...etc) then use a billboard and spritesheet offsets to handle animations.
    To simplify the spritesheet I intent to use rows to handle the perspective and columns to handle the animations (movement, attack animations, death...etc).

    Included is a scribbling to help illustrate what I have in mind.
    $Scan_Pic0004.png

    I FOUND THIS LINK... which seems to be right up my ally but I am having troubles implementing the code.

    robertbu presented some code which seems Ideal:
    Code (csharp):
    1. var dir = player.position - transform.position;
    2.     var angle = Mathf.Atan2(dir.z, dir.x);
    3.     if (angle < 0.0)
    4.     angle = angle + 360.0;
    5.     var index = Mathf.RoundToInt(angle / 45.0);
    Many errors come when I try to customize this code for my ends...referencing the main camera instead of this "player"...trying to have the script reference "this" so it references the parent object so I can use it as a template for different enemies...

    One step at a time and all I was hoping someone could shed some light on how to get this eight way index working...if someone could demonstrate even one index (horizontal perhaps) it would be simple to adjust it for the other (vertical) from there I have the know how to apply this to my spriting method and would be happy to post a completed script so that this could be some mutual learning for us and any who look this up.



    P.S. sorry for all the attached pics, I was having a bit of trouble sizing correctly.
     

    Attached Files:

  2. Brian-Stone

    Brian-Stone

    Joined:
    Jun 9, 2012
    Posts:
    222
    Your algorithm is fundamentally correct, but the Atan2 function returns the angle in radians, not degrees. Its range is −π to π.

    Code (csharp):
    1.  
    2. var dir = player.position - transform.position;
    3. var angle = (Mathf.Atan2(dir.z, dir.x) + Mathf.PI) * (180 / Mathf.PI); // range 0 to 360
    4. var index = Mathf.RoundToInt(angle / 45) % 8; // range 0 to 7
    5.  
     
  3. Buzzbomb

    Buzzbomb

    Joined:
    Mar 13, 2013
    Posts:
    8
    This explains quite a bit!

    I'm going to try and implement this shortly and get you an update...and hopefully soon a working script/demo.
     
  4. Buzzbomb

    Buzzbomb

    Joined:
    Mar 13, 2013
    Posts:
    8
    Okay I'm once again wrestling with this code applying Brian Stone's input...ugh my head.

    Referencing the current camera and disassembling a previous functional spritesheet animation script...assuming the maintexture has other scripts assuring it is a billboard that faces the main camera here is my script so far...

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class eightwayface : MonoBehaviour {
    5.    
    6.     public int rowcount = 8;
    7.     public int colcount = 1;
    8.    
    9.     private int rownumber = atanindex;
    10.     public int colnumber = 0;
    11.    
    12.     private Vector2 offset;
    13.  
    14.     // Use this for initialization
    15.     void Start () {
    16.    
    17.     }
    18.    
    19.     // Update is called once per frame
    20.     void Update () { SetHorizView(int rowcount, int colcount, int rownumber, int colnumber ); }
    21.        
    22.     void SetHorizView(int rowCount, int colCount, int rowNumber, int colNumber, ){
    23.        
    24.        
    25.         //calculate size of every cell
    26.         float sizeX = 1.0f / colCount;
    27.         float sizeY = 1.0f / rowCount;
    28.         Vector2 size = new Vector2 (sizeX,sizeY);
    29.        
    30.         //splint horiz' and vert' index
    31.         var uIndex = index % colCount;
    32.         var vIndex = index / colCount;
    33.        
    34.         // build offset
    35.         // v coordinate is the bottom of the image in opengl so we need to invert.
    36.         float offsetX = (uIndex+colNumber) * size.x;
    37.         float offsetY = (1.0f - size.y) - (vIndex + rowNumber) * size.y;
    38.         Vector2 offset = new Vector2(offsetX,offsetY);
    39.        
    40.         var dir = Camera.current.position - transform.position;
    41.         var angle = (Mathf.Atan2(dir.z, dir.x) + Mathf.PI) * (180 / Mathf.PI); // range 0 to 360
    42.         var atanindex = Mathf.RoundToInt(angle / 45) % 8; // range 0 to 7
    43.  
    44.         renderer.material.SetTextureOffset ("_MainTex", offset);
    45.         renderer.material.SetTextureScale  ("_MainTex", size);
    46.    
    47.     }
    48.  
    49.    
    50. }
    the current goal for this is using a sprite sheet with 8 rows and 1 column is to have the offsets used to switch rows to give the illusion that it is facing the current camera

    aside from a few errors I am having trouble thinking of how to apply the "atanindex" var to the SetTextureOffset...Any thoughts?
     
  5. Buzzbomb

    Buzzbomb

    Joined:
    Mar 13, 2013
    Posts:
    8
    WOOOOOOO!!! NO ERRORS!!!

    thing is ...it doesn't seem to do anything lol.

    Current version of my code...

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. class HorizFace : MonoBehaviour
    5. {
    6.     public int columns = 1;
    7.     public int rows = 8;
    8.     public float framesPerSecond = 0f;
    9.  
    10.     //the current frame to display
    11.     private int index = 0;
    12.  
    13.     void Start()
    14.     {
    15.         StartCoroutine(updateTiling());
    16.  
    17.         //set the tile size of the texture (in UV units), based on the rows and columns
    18.         Vector2 size = new Vector2(1f / columns, 1f / rows);
    19.         renderer.sharedMaterial.SetTextureScale("_MainTex", size);
    20.     }
    21.  
    22.     private IEnumerator updateTiling()
    23.     {
    24.         while (true)
    25.         {
    26.             //move to the next index
    27.             index++;
    28.             if (index >= rows * columns)
    29.                 index = 0;
    30.  
    31.             //split into x and y indexes
    32.             Vector2 offset = new Vector2((float)index / columns - (index / columns), //x index
    33.                                           (index / columns) / (float)rows);  //y index
    34.            
    35.             var dir = Camera.current.transform.position - transform.position;
    36.             var angle = (Mathf.Atan2(dir.z, dir.x) + Mathf.PI) * (180 / Mathf.PI); // range 0 to 360
    37.             var atanindex = Mathf.RoundToInt(angle / 45) % 8; // range 0 to 7
    38.  
    39.             renderer.sharedMaterial.SetTextureOffset("_MainTex", atanindex * offset);
    40.  
    41.         }
    42.  
    43.     }
    44. }
    I have a feeling I'm applying the atanindex wrong...perhaps multiplying the offset by this is not the way to go. Any thoughts guys?