How to make a sprite change based on it's position relative to the player's

Viewed 98

I'm trying to achieve a 2.5D effect with a sprite like the effect in this https://www.youtube.com/watch?v=-Eb99eujEik video, but it selects the wrong sprite at certain angles

the code I have so far is:

void Update()
{

    float angle = Quaternion.LookRotation(player.transform.position, transform.position).y - transform.rotation.y;

    print(angle + ",   " + Mathf.Abs(Mathf.Round(angle * 100 / 12.5f)) + ",   " + Quaternion.LookRotation(player.transform.position, transform.position).y * 100);

    switch (Mathf.Abs(Mathf.Round(angle * 100 / 12.5f)))
    {
        case 0:
            sprite_comp.sprite = N;
            break;
        case 1:
            sprite_comp.sprite = NW;
            break;
        case 2:
            sprite_comp.sprite = W;
            break;
        case 3:
            sprite_comp.sprite = SW;
            break;
        case 4:
            sprite_comp.sprite = S;
            break;
        case 5:
            sprite_comp.sprite = SE;
            break;
        case 6:
            sprite_comp.sprite = E;
            break;
        case 7:
            sprite_comp.sprite = NE;
            break;
    }
}

1 Answers

I solved this problem. This is an 8-directional sprite algorithm whose component works on the character that has a SpriteRenderer. This algorithm divides the sections into 22.5 degrees to determine which side should be selected. It also takes into account both the rotation of the camera and the rotation of the character due to the function of the angle of calculation from the forward of the camera and the character.

private SpriteRenderer spriteRenderer;

public Transform plane;
public Camera cam;

private const float step = 22.5f;

public Sprite N, NW, W, SW, S, SE, E, NE;
public void Start() => spriteRenderer = GetComponent<SpriteRenderer>();
public void Update()
{
    var projected = Vector3.ProjectOnPlane(cam.transform.forward, plane.up);
    var angle = Vector3.SignedAngle(projected, plane.forward, plane.up);
    
    var AbsAngle = Mathf.Abs(angle);
    
    if (AbsAngle < step) spriteRenderer.sprite = N;
    else if (AbsAngle < step*3) spriteRenderer.sprite = Mathf.Sign(angle) < 0 ? NW : NE;
    else if (AbsAngle < step*5) spriteRenderer.sprite = Mathf.Sign(angle) < 0 ? W : E;
    else if (AbsAngle < step*7) spriteRenderer.sprite = Mathf.Sign(angle) < 0 ? SW : SE;
    else spriteRenderer.sprite = S;
    
    Billboard(spriteRenderer.transform, cam);
}

You will also need another code to hold the sprite to the camera. A billboard method is also needed to solve the problem.

public void Billboard(Transform character, Camera mainCamera)
{
    var dir = plane.position - mainCamera.transform.position;
    var LookAtRotation = Quaternion.LookRotation(dir);
    
    var LookAtRotationOnly_Y = Quaternion.Euler(character.rotation.eulerAngles.x, LookAtRotation.eulerAngles.y,character.eulerAngles.z);
    character.rotation = LookAtRotationOnly_Y;
}

Result

enter image description here

Related