Update : I tried removing everything, even the player, and there is still a lag ! It seems like half the problem comes from the looping background, it’s as if on some irregular number of seconds, there is a jerky movement as if the background pauses and generates again.
Hello everybody,
I’ve been scratching my head over this problem of general jitteriness/latency all over my minimal project (2d, mobile). At first – as seen in the first video – there is just a player with camera moving to simulate a sort of runner game, there is some jitteriness there but it’s still minimal, the moment other game objects are introduced – cats, as seen in the second video – the game become more jittery, both the game objects and the background.
When i try to add interpolate to game objects, it just makes the player jump become inconsistent without solving or improving the latency/jitteriness. So i suspect it may have something to do with the way framerates are processed, in another phone there is less lag – but still more than enough to ruin the game -
I know the problem is complicated for a beginner, having to do with Unity Game Engine/Frame Rates and i don’t expect some magical 1 paragraph solution, but i’ve been searching the whole of the internet just looking for a hint, an idea of where/what i have to look for and i still can’t find any. So i’m asking for the community generosity in directing me towards any hint/direction/rough draft of where to go.
Those videos are from a test on mobile. (In the first 5/6 seconds there is a jitteriness from the recording app, don’t mind that)
Video 1 :
Video 2 (with GameObjects) :
Video 3 (with a static GameObject, to see if the problem comes from the animator/animation) :
Code and more elements/pictures :
Player GameObject Code :
(
What i’m trying to do with the Player Code as it may seem – and it is – convoluted. Player moves once (or twice if double tap under a certain time constraint) top or bottom. With a constraint on top and a constraint on bottom.
)
```csharp
**using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class Player : MonoBehaviour
{
public float playerSpeed;
public Animator animator;
private Rigidbody2D rb;
private Vector3 playerPosition;
// private Vector3 playerDirection;
public float directionY;
private Rect top;
private Rect bottom;
private bool isJumping;
// public bool AnJumping;
float vertical = 0;
float timer;
// float moveLimiter = 2f;
float waitTime = 0.2f;
float speed = 2f;
float jumpCount = 0f;
float jumpLimit = 10f;
public static bool paused;
static float tapCount = 0f;
bool isSecondJumping = false;
bool once = true;
static bool pauseButton;
float jumpTimer = 0.5f;
float secondJumpTimer = 0.25f;
[SerializeField] private AudioSource jumpSoundEffect;
Touch touch;
public TextMeshProUGUI StartText;
void Awake()
{
StartText = GetComponent<TextMeshProUGUI>();
}
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody2D>();
waitTime = 3f;
vertical = 0;
}
void tryJump(string position)
{
tapCount++;
Debug.Log("Display Number Taps : " + tapCount);
if (tapCount > 1) // If player tapped more than once
{
Debug.Log("Display Number Taps : Yes You Here");
}
if (position == "Top")
{
Debug.Log("Movement Activated : Top");
vertical = speed;
jumpCount = 0f;
}
else if (position == "Bottom")
{
Debug.Log("Movement Activated : Bottom");
vertical = -speed;
jumpCount = 0f;
}
}
// Update is called once per frame
void Update()
{
playerPosition = this.gameObject.transform.position;
bottom = new Rect(0, 0, Screen.width, Screen.height / 4.5f);
top = new Rect(0, Screen.height / 4, Screen.width, Screen.height / 1.50f);
if (jumpTimer > 0 && isJumping)
// If the player is Jumping and the JumpTimer is still over 0, we decrease the value of
// the jumpTimer.
{
jumpTimer -= Time.deltaTime;
}
if (jumpTimer <= 0)
// Once the Jump Timer value is inferior to 0 (jump timer over), the jump is Over, we assign false to isJumping.
{
isJumping = false;
jumpTimer = 0.20f;
tapCount = 0;
}
if (secondJumpTimer <= 0)
// Once the secondJump timer value is inferior to 0 (second jump timer over), we reset the value of
// secondJumpTimer, a player can make the second jump during this interval (0.15f)
{
once = true;
secondJumpTimer = 0.15f;
isSecondJumping = false;
}
if (secondJumpTimer > 0 && isSecondJumping)
// If the player is still in the interval of the second jump, we decrease the value of
// the secondjumpTimer.
{
secondJumpTimer -= Time.deltaTime;
}
if (!isJumping | tapCount == 1)
// If it’s either the first or second Jump during the second Jump Intervall.
{
if (Input.touchCount > 0) // If player wants to Jump
{
isSecondJumping = true;
Debug.Log("Display if Click Detected");
if (!isJumping) { isJumping = true; }
touch = Input.GetTouch(0);
if (top.Contains(touch.position) && playerPosition.y < 0.98f)
{
if (once)
// To make the code generate only once as to avoid moving up ad infinitum
{
once = false;
tryJump(“Top”); // Player move up.
}
}
else if (bottom.Contains(touch.position) && playerPosition.y > -0.64f)
{
if (once)
// To make the code generate only once as to avoid moving down ad infinitum
{
once = false;
tryJump(“Bottom”); // PLayer move down.
}
}
}
}
}
void FixedUpdate()
{
if (vertical != 0) { jumpCount += 1f; }
// We increase the JumpCount by 1 unless vertical = 0 (which mean jump is over).
if (jumpCount >= jumpLimit) // We reached the end of the jumpCount, we set vertical to 0.
{
vertical = 0f;
}
rb.velocity = new Vector2(0, (vertical * 2));
}}**
** **Cat GameObject Code :** **
csharp
**[/U]using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BlackCat : MonoBehaviour
{
public Animator animator;
public static float finalScore = 0;
public GameObject soundEffects;
// public Animator animator;
private GameObject player;
private Vector3 positionPlayer;
public Vector3 positionBlackCat;
public float LastPosition;
public string TypeLastPosition;
public float directionYinitial = 1;
private Rigidbody2D rb;
private SpriteRenderer renderer;
[SerializeField] private AudioSource meowSoundEffect;
// Start is called before the first frame update
void Start()
{
finalScore = 0;
player = GameObject.FindGameObjectWithTag(“Player”);
rb = GetComponent();
renderer = GetComponent();
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.tag == “sideBorder”)
{
Destroy(this.gameObject);
}
else if (collision.tag == "Player") // If there is a collusion with white cat
{
// Destroy(player.gameObject);
}
else
{
meowSoundEffect.Play();
//Debug.Log("No Collusion Here White Cat");
}
}
}
void Update()
{
ScoreManager.score += finalScore;
finalScore = 0;
if (GameObject.FindGameObjectWithTag("Player") != null)
{
positionPlayer = player.gameObject.transform.position;
}
}
void FixedUpdate()
{
}
}**
** **SpawnGame Objects Code :** **
csharp
**using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class spawnAllCats : MonoBehaviour
{
public float blackCatScore;
public bool isGenerated;
public GameObject WhiteCats;
public GameObject BlackCats;
public float maxX;
public float minX;
public float maxY;
public float minY;
private float timeBetweenSpawn = 0.1f;
public float spawnTime;
private float randomNumber = 0;
float randInterval;
float actualHorizontal = 0f;
static int catNumber = 0;
private float randomX;
public static bool isGeneratingCat;
string generateType = "White";
float timer;
float waitTime;
float randomY;
// Zones where game objects will be placed
float verticallevel1 = 2.6f;
float verticallevel2 = 1.8f;
float verticallevel3 = 1.16f;
float verticallevel4 = -1.5f;
float verticallevel5 = -2.25f;
private bool oneTime = false;
public static List<string> lastAllCats = new List<string>();
public static List<float> lastAllCatsLocation = new List<float>();
void Start()
{
isGeneratingCat = false;
randomX = 0;
waitTime = 1.5f;
timer = 0f;
randomY = 0;
spawnTime = 0;
}
// Update is called once per frame
void Update()
{
if (!isGeneratingCat && Time.time > spawnTime && !Player.paused) // If the process of generating cat isn't ongoing and if
// enough time has lapsed
{
if (randomNumber == 0) // End of instanciation, we start a new one.
{
randomNumber = Random.Range(1, 3);
// We generate a random number to generate either a white or black cat.
}
if (randomNumber == 1)
// We'll generate a white cat here
{
generateType = "White";
// We will generate a white cat
// 1 : We generate an X axis, and a Y axis.
float[] arrayVerticals = new float[] { verticallevel1, verticallevel2, verticallevel5, verticallevel3, verticallevel4, verticallevel5 };
// We create an array containing the possible values of the Y axis where
// the cats will be placed.
// float[] arrayVerticals = new float[] { 3.4f, -1.7f, -1.7f,- 3.7f }
int randNumber = Random.Range(0, 6); // We create a random number that will serve as the index of the arrayVerticals array.
randomY = arrayVerticals[randNumber];
randomX = Random.Range(minX, maxX);
actualHorizontal = randomX + transform.position.x;
// We get the horizontal value that will serve to generate the cat
} // We set isGenerating Cat is true, so that this process of cat generation isn't engaged again untill / waitTime has lapsed
isGeneratingCat = true;
}
else if (randomNumber == 2)
{
generateType = "Black";
// We will generate a black/orange cat
// We create an array containing the possible values of the Y axis that will
// serve to spawn the cat
float[] arrayVerticals = new float[] { verticallevel1, verticallevel2, verticallevel2, verticallevel3, verticallevel3, verticallevel4, verticallevel5 }; // We create an array containing the possible values of the Y axis where the cats will be placed
int randNumber = Random.Range(0, 7);
// We create a random number that will serve as the index of the arrayVerticals array.
randomY = arrayVerticals[randNumber];
randomX = Random.Range(minX, maxX);
actualHorizontal = randomX + transform.position.x; ; // We save the position of the last
cat in the actualHorizontal variable
// We set isGenerating Cat is true, so that this process of cat generation isn't engaged again untill / waitTime has lapsed
isGeneratingCat = true;
}
if (isGeneratingCat) // If isGenerating Cat is true (we have our x/y axis and our waittime and isGenerating cat is set to true)
{
timer += Time.fixedDeltaTime; // We run a timer, this time will serve to generate a cat once it reaches the relevant waitTime.
Debug.Log("Debug 1, Timer now shows " + timer);
}
if (timer >= waitTime) // if the time of WaitTime has elapsed.
{
timer = 0f; // We reset the timer once it has reached its end
if (generateType == "White") // We genenerate a white cat
{
SpawnWhiteCat(randomX, randomY);
}
else if (generateType == "Black") // We generate a black cat
{
SpawnBlackCat(randomX, randomY);
}
}
}
void SpawnWhiteCat(float randomX, float randomY)
{
// We generate a white cat using the coordinates we received as parameters of the function.
Instantiate(WhiteCats, transform.position + new Vector3(randomX, randomY, 0), transform.rotation);
// We set isGeneratingCat to false, so that the cat generating process can re-start again.
isGeneratingCat = false;
randomNumber = 0;
oneTime = false;
spawnTime = Time.time + timeBetweenSpawn;
}
void SpawnBlackCat(float randomX, float randomY)
{
Instantiate(BlackCats, transform.position + new Vector3(randomX, randomY, 0), transform.rotation);
// We set isGeneratingCat to false, so that the cat generating process can re-start again.
isGeneratingCat = false;
randomNumber = 0;
oneTime = false;
spawnTime = Time.time + timeBetweenSpawn;[/B]
}
}**
** **Looping Background Code :** **
csharp
**using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class loopingBackground : MonoBehaviour
{
public float backgroundSpeed;
public Renderer backgroundRenderer;
// Start is called before the first frame update
// Update is called once per frame
void Update()
{
backgroundRenderer.material.mainTextureOffset += new Vector2(backgroundSpeed * Time.deltaTime, 0f);
}
}**
** **CameraMovement Code :** **
csharp
**using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class cameraMovement : MonoBehaviour
{
public GameObject RunTimerPanel;
[SerializeField] TextMeshProUGUI RunText;
public static float cameraSpeed;
[SerializeField] private AudioSource runSoundEffect;
void Start()
{
cameraSpeed = 12f; }
void Update()
{
transform.position += new Vector3(cameraSpeed * Time.deltaTime, 0, 0);
}
}**
```
Background :
Backgr1 - Album on Imgur
Player : Player1 - Album on Imgur
SpawnPoints : Imgur: The magic of the Internet
BlackCat (Orange Cat) : Imgur: The magic of the Internet
Thank you in advance.