Jittery Billboarding: Agh!

I’m working on a Doom clone. That means billboarded sprites and a 3D environment. Unfortunately I’m getting really serious jitter when the player walks or looks around a sprite, and I’m really not sure why.

You can see the issue here (the camera is locked to the WolfGuard): Dropbox - Error - Simplify your life

This is the script I’m using to handle the billboarding effect:

using UnityEngine;
using System.Collections;

public class twoDeeObject : MonoBehaviour {
	public Quaternion actualRotation;
	public SpriteSet currentSprites;
	private SpriteRenderer myRenderer;

	void Start(){
		myRenderer = gameObject.GetComponent<SpriteRenderer>();
		actualRotation.eulerAngles = Vector3.forward;
	}
	

	void Update () {
		//billboarding
		transform.LookAt(transform.position + Camera.main.transform.rotation * Vector3.back,Camera.main.transform.rotation * Vector3.up);

		//Angle Selection
		float cameraAngleDifference = Camera.main.transform.rotation.eulerAngles.y - actualRotation.eulerAngles.y;
		while (cameraAngleDifference < -180) cameraAngleDifference += 360;
		while (cameraAngleDifference > 180) cameraAngleDifference -= 360;
		myRenderer.sprite = currentSprites.S;
		if (cameraAngleDifference > 22.5){myRenderer.sprite = currentSprites.SE;}
		if (cameraAngleDifference > 67.5){myRenderer.sprite = currentSprites.E;}
		if (cameraAngleDifference > 112.5){myRenderer.sprite = currentSprites.NE;}
		if (cameraAngleDifference > 157.5){myRenderer.sprite = currentSprites.N;}

		if (cameraAngleDifference < -22.5){myRenderer.sprite = currentSprites.SW;}
		if (cameraAngleDifference < -67.5){myRenderer.sprite = currentSprites.W;}
		if (cameraAngleDifference < -112.5){myRenderer.sprite = currentSprites.NW;}
		if (cameraAngleDifference < -157.5){myRenderer.sprite = currentSprites.N;}

	}
}

[System.Serializable]
public class SpriteSet{
	public Sprite N;
	public Sprite NE;
	public Sprite E;
	public Sprite SE;
	public Sprite S;
	public Sprite SW;
	public Sprite W;
	public Sprite NW;

}

I would be very grateful for any insights
Thanks!

I’ve worked out that this is a vsync issue. By setting vSyncCount to 0 I remove that jittering, presumably because the rotation is always accurate. Problem is, now there is no vsync and the sprites tear. I believe that a new solution is going to be required to completely smooth this out.

Are you using deltaTiming ? if not then that’s probably why. You should probably look into your routine for rotating to face as well, as this is likely the real culprit. Ripped out some code from an ancient doom project I did for laughs one night ages ago (might help):

Try:

using UnityEngine;
using System.Collections;


public class Billboard:MonoBehaviour
{
    public static Camera cam;
    public static Transform camTrans;
    private Transform trans;
    private Renderer rend;


    void Start() 
    {
        if (cam == null)
        {
            cam = Camera.main;
            camTrans = cam.transform;
        }
        trans = transform;
        rend = renderer;
    }


    void Update()
    {
        if (rend.isVisible)
        {
            trans.LookAt(trans.position + camTrans.rotation * Vector3.back, camTrans.rotation * Vector3.up);
        }
    }
}

Place on thing you want to billboard.

And for sprite frame to angle with relative camera ie camera looks one direction and sprite wants to face another:

int ConvertAngleToFrames(float ta)
{
float ca = camTrans.rotation.eulerAngles.y-180f;
float relativeAngle = S2.AngleDiff(ta, ca)/360f;
int index = (int)( (11f+relativeAngle)*22f )%21;
return index;
}

Where ta is the sprites actual angle internally. This is a hacked routine assuming there’s 22 frames or something (11 is half) - a complete and utter bodge for a prototype I did years ago. So take from it what you will :smile:

Thanks for the code, but as far as I can make out we are using virtually identical code to achieve this result.

Basically what I’ve worked out is that the sprite doesn’t always rotate in between the player moving and the scene rendering. With vsync turned off the sheer volume of renders smooths this effect out. I tried moving the billboarding script into fixedupdate to see if I could make it happen after the player rotation, but to no avail. I’d love to be corrected, but I don’t believe that there is a way to resolve this situation without a way to time the rotation with the renderer.