Next code below acts different on Android, while in Editor it acts as supposed:
private IEnumerator CountTo(int target)
{
yield return new WaitForSeconds(0.5f);
int start = 0;
do
{
ScoreText.text = string.Format(scoreText, start);
if (start != 0)
{
SoundManager.instance.Play(ScoreSound, default, 0.4f);
}
start++;
yield return new WaitForSeconds(0.33f);
}
while (start <= target);
}
In editor, when it called, it waits for 0.5 seconds before launch (to wait Complete level sound to play), counts to target one by one with playing ScoreSound each time (except the first one) when score changes.
On Android it firsts plays all of the the needed ScoreSound sounds and only then, SLOWLY (almost like with lags) changes the UI score. In debugger, step by step, everything works fine. Using the Profiler, FPS is stable when this happens.
Any idea what can be causing this?
Thanks!
OK, guys, sorry, I figured it out, the answer is actually really stupid... So it turns out that this was happening because of the Post Processing Stack's Depth of Field, it was activated during Level Complete phase and when the CountTo was called, so it seems that these two somehow interfered each other, so I've got what I've got.
Sorry again! Thanks!
Related
I am creating a rythm VR game for google cardboard, inspired by Beat Saber on PSVR and Oculus Rift.
The concept is that blocks with different directions come at you, following the rythm of the music, just like in Beat Saber.
For every music I have created a ScriptableObject called music, with every parameter it should contain like the difficulty of the song, the name, etc. but also an array of Vector3 called notes : the first float of the Vector corresponds to the time the note should be beaten in the rythm of the music starting from 0: ScriptableObject
Then in a script called SlashSpawnManagement, where every thing is based on WaitForSeconds(), I spawn the blocks to smash. It's realy hard for me to explain wih words the order I do it in, so here is an image : Explanation
In theory, what this script does, it waits for some time, spawns a block, waits for some time, spawn a block, etc. The logic seems okay, but here's the weird part. As you play the song the distance between each block gradually becomes bigger and bigger, meaning the blocks become more and more out of sync with the music. It starts very well, but at the end of the music there is at least a 5s gap.
I figured it has something to do with the frame rate drop, so I tried to set the frameRate to something low with :
QualitySettings.vSyncCount = 0; // VSync must be disabled
Application.targetFrameRate = 30;
But it doesn't solve the problem. I tried with WaitForSecondsRealtime instead of WaitForSeconds, but nothing changes. I have read somewhere that WaitForSeconds depends on the frame rate... Where I calculated the time, I tried sustractng h divided by a number to even out the gradual gap. This works for some blocks but not every block: Notes[j][0] - h / 500
So here's my question, how do I make the WaitForSeconds, or any other method consistent with the seconds provided ?
Thank you In advance,
PS : For more clarifications, please ask and please forgive my typos and my english :)
If you want something to happen in regular time intervals, it is important to make sure that errors don't accumulate.
Don't:
private IEnumerable DoInIntervals()
{
while (this)
{
yield return new WaitForSeconds(1f); // this will NOT wait exactly 1 second but a few ms more. This error accumulates over time
DoSomething();
}
}
Do:
private IEnumerable DoInIntervals()
{
const float interval = 1f;
float nextEventTime = Time.time + interval;
while (this)
{
if (Time.time >= nextEventTime)
{
nextEventTime += interval; // this ensures that nextEventTime is exactly (interval) seconds after the previous nextEventTime. Errors are not accumulated.
DoSomething();
}
yield return null;
}
}
This will make sure your events happen in regular intervals.
Note: Even though this will be regular, it does not guarantee that it will stay in sync with other systems like audio. That can only be achieved by having a shared time between systems, like spender mentioned in his comment on your question.
Trying to use WaitForSeconds the timing of audio and hope for the best is hoping a big hope.
Have a list of Vector3s prepared in advance. If you want to prepare the list using the rythm - it will work. Use AudioSource's time to check every Update whether the timing is right and spawn a block at that moment.
void Update () {
SpawnIfTimingIsRight();
}
void SpawnIfTimingIsRight() {
float nextTiming = timingsArray[nextIndex].x;
// Time For Block To Get To Position
float blockTime = this.blockDistanceToTravel / this.blockSpeed;
float timeToSpawnBlock = nextTiming - blockTime;
if (this.audioSource.time >= nextTiming && (this.audioSource.time - Time.deltaTime) < nextTiming) {
// Spawn block
}
}
I've encountered a problem, and need help to figure out what's happening. The idea is to synchronize 2 or more android devices with respect to a GPS location timestamp. I've heard that GPS time is very accurate, unlike system time, which may vary across few seconds. However the results I get are not what I expected.
void Start() {
Input.location.Start ();
double UTC_timestamp = Input.location.lastData.timestamp;
Input.location.Stop ();
}
So in this case, UTC_timestamp represents the total number of seconds since January 1st 1970, 00:00:00.
But if I request a timestamp on 2 different devices, I am getting quite a sure difference, and my attempts to synchronize them via satellite's timestamp fails.
Here is how I tested that:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class GPSTime: MonoBehaviour {
double UTC_timestamp;
public Text txt_UTC;
IEnumerator Start() {
UTC_timestamp = getGPSTime ();
while (Application.isPlaying) {
yield return new WaitForSeconds (1);
UTC_timestamp ++;
}
}
void Update() {
print("UTC: "+ UTC_timestamp);
txt_UTC.text = "UTC: " + UTC_timestamp;
}
private double getGPSTime() {
Input.location.Start ();
UTC_timestamp = Input.location.lastData.timestamp;
Input.location.Stop ();
return UTC_timestamp;
}
}
I run this on two different devices, and the timestamp I am getting differs quite significantly:
So out of three app launches I get the following:
DEVICE 1
1) 1438782375.605
2) 1438782610.260
3) 1438782681.926
4) 1438782960.266
DEVICE 2
1) 1438782505.306
2) 1438782680.011
3) 1438782675.226
4) 1438782967.400
So first launch differs by ~130 seconds!!! Second trial differs by ~70 seconds, and third trial differs by 6-7 seconds. Fourth trial differs by around 7 seconds.
Why such strange differences? What can I do to get the best results possible?
Seems that I have found my answer after all. In case anyone else is facing these issues, here is what I found out.
Input.location.Start (); //initializer, takes two arguments
Default arguments are:
Input.location.Start (10, 10);
both are of type float, first is accuracy (10 meters) and the second is how much the device has to be displaced to request a pulse from the satellite, (10 meters). So the reason to why I was getting such strange numbers for timestamp on both devices, is that I did not consider that I actually had to move, for the time to get updated. So what I did is I decreased the accuracy to 100 meters (I do not need such high accuracy for getting a timestamp, as 10 meters) and set the displacement value to zero, and I got perfects PPS (pulse per second) where both devices were in sync, which is exactly what I needed.
Another point to make, gps signals don't get through very well if you are indoors. Much depends on whether the sky is open and how tall the buildings are around you. That factors in as well, in case you are experiencing some gps fix troubles in this context. However I can confirm that GPS time is very accurate indeed, and works very well on unity engine on android devices. iOS not tested yet.
Im creating an asteroids game and am having an issue trying to get my player ship to fire.
Below is the code for what i believe should get the player ship to fire
public void Fire()
{
if (RocketshotDelay >= 0)
RocketshotDelay--;
if (RocketshotDelay <= 0)
{
rocketshotPosition = new Vector2(rocketshotPosition.X + 32 - rocketshotTexture.Width / 2, rocketshotPosition.Y + 30);
isVisible = true;
if (RocketshotDelay == 0)
RocketshotDelay = 15;
public void UpdateRocketshot()
{
rocketshotPosition.Y = rocketshotPosition.Y - speed;
if (rocketshotPosition.Y <= 0)
isVisible = false;
}
I think this should get my player ship to fire but as of yet, i havent been able to get the ship to fire. Any suggestions on any issues in my code would be grateful. Cheers
I can't answer in the comments yet.
Possible issues:
Make sure if you're using the "base.Update()" code and "base.Draw()" functions that you have done "Components.Add(RocketShot Instance Name)" or "Components.Add(this)"
Is the firing code located inside of the actual rocketship or rocketshot class?
If it is inside of the rocketshot class (which it seems like it is), then ask yourself and see where the initial rocketshot position is. It seems as though you simply offset it, but where is it being offset from? is the rocketshot perhaps off at x:0 y:0 to begin with? or are you sure it's tracking next to the ship?
Your rocketshot delay might also not be working correctly. You only reset the rocketshot to 15 if it is EQUAL to 0. Not if it is less than. But you can trigger that code even if it is -1 or anything else negative. This means that maybe you'll get your first shot, but if the delay goes beyond 0 (-1 to anything else negative), your bullet won't reset. If this happens your rocketshot will probably keep reseting.
Make sure your speed is reasonable. Maybe first test it with a small number.
Make sure your trigger and fire code considers a button being released and not just pressed and held down. Meaning use a previousKeyState and a currentKeyState. Otherwise it might keep triggering. (And with the delay issue this might cause it to always reset all the time).
if (RocketshotDelay <= 0) //This will trigger and reset all the time
RocketshotDelay = 15;
I have a simple 2D top down survival game where the player simply has to 'run away'/ not collide with the enemies on screen for 30 seconds each round.
After every increment in level the number of each enemy increases.
The Problem
One of my enemy types is in a searching/sleeping state until the player comes a certain distance towards it, then it is in a chasing state, and stays that way until the round ends.
On the earlier rounds where there's only around 30 enemies on screen at once all behaviours work fine. However when i start getting to around a 60+ enemy count this certain enemy seems to chase the player for a little while then seems to go back into the sleeping state - which seems odd considering the following;
public override void Update(SpriteManager inManager)
{
this.spriteRectangle.X = (int)position.X;
this.spriteRectangle.Y = (int)position.Y;
if (this.collisionRectangle.Intersects(inManager.player.spriteRectangle))
this.spriteState = SpriteState.Chasing;
if (this.spriteState == SpriteState.Chasing)
{
CheckForPlayer(inManager);
if (this.spriteRectangle.Intersects(inManager.player.spriteRectangle))
{
inManager.player.spriteState = SpriteState.Dead;
}
}
base.Update(inManager);
}
private void CheckForPlayer(SpriteManager inManager)
{
if (this.position.X > inManager.player.position.X)
this.position.X -= X_SPEED;
else
this.position.X += X_SPEED;
if (this.position.Y > inManager.player.position.Y)
this.position.Y -= Y_SPEED;
else
this.position.Y += Y_SPEED;
}
Can anyone shed any light onto why they think this problem is occurring, my only thoughts are that with a high sprite (maximum is 108) maybe they're all not having time to check for the player, although when I think about that more to me it makes no sense.
Cheers
Without full code it is hard to tell, but I take it it is a little mistake somewhere. You should try debugging it and checking if the state is Chasing or if it really did change states. I've also ran into problems with lag with certain amounts of objects (Probably not the problem) so that could also be a possibility.
Update: I have uploaded a video showing the stutter here: http://intninety.co.uk/xnastutter.mp4 you may have to look closely in the video if you are not viewing it at 1920x1080, but you'll see that there is a rather distinct stutter when moving every 2 seconds or so, I'd recommend viewing it in Windows Media Player rather than your web browser to ensure the video itself isn't choppy and thus preventing you seeing the actual stutter
I'm recently picking up a project I started a while ago, however I am still struggling to solve the problem I left it at!
At the moment I have a very simple application which just has a single sprite on screen and is moved around using the directional keys. The problem is every two seconds or so, the game stutters and the sprite appears to jump backwards and then back forwards very quickly.
The sprite itself is a 55x33 bitmap, so isn't anything large, and the code in use is as follows. Hopefully this is enough to get the ball rolling on some ideas as to what may be the problem, if a video is required to see exactly how the stuttering looks I can put one together and upload it somewhere if need be.
As you'll see in the code it does compensate for time lost between frames by making the movement greater should it happen, however that drop is happening very consistently time wise, which is leading me to believe I'm doing something wrong somewhere.
I've tried on a few different machines but the problem persists across all of them, if anyone has any ideas or can see where it is I'm messing up it'd be greatly appreciated if you could point it out.
Thanks :)
Constructor of the Game Setting up the Graphics Device Manager
graphics = new GraphicsDeviceManager(this);
graphics.IsFullScreen = true;
graphics.SynchronizeWithVerticalRetrace = false;
graphics.PreferredBackBufferWidth = 1920;
graphics.PreferredBackBufferHeight = 1080;
Content.RootDirectory = "Content";
this.IsFixedTimeStep = false;
Code from the Game's Update Method
KeyboardState keyboard = Keyboard.GetState();
GamePadState gamePad = GamePad.GetState(PlayerIndex.One);
if (keyboard.IsKeyDown(Keys.Escape)) {
this.Exit();
}
if ((keyboard.IsKeyDown(Keys.Left)) || (gamePad.DPad.Left == ButtonState.Pressed))
{
this.player.MoveLeft((float)gameTime.ElapsedGameTime.TotalMilliseconds);
} else if ((keyboard.IsKeyDown(Keys.Right)) || (gamePad.DPad.Right == ButtonState.Pressed))
{
this.player.MoveRight((float)gameTime.ElapsedGameTime.TotalMilliseconds);
}
if ((keyboard.IsKeyDown(Keys.Up)) || (gamePad.DPad.Up == ButtonState.Pressed))
{
this.player.MoveUp((float)gameTime.ElapsedGameTime.TotalMilliseconds);
} else if ((keyboard.IsKeyDown(Keys.Down)) || (gamePad.DPad.Down == ButtonState.Pressed))
{
this.player.MoveDown((float)gameTime.ElapsedGameTime.TotalMilliseconds);
}
base.Update(gameTime);
The "Move" Methods seen in the above Update Method
public void MoveLeft(float moveBy)
{
this.position.X -= (moveBy * this.velocity.X);
}
public void MoveRight(float moveBy)
{
this.position.X += (moveBy * this.velocity.X);
}
public void MoveUp(float moveBy)
{
this.position.Y -= (moveBy * this.velocity.Y);
}
public void MoveDown(float moveBy)
{
this.position.Y += (moveBy * this.velocity.Y);
}
The Game's Draw Method
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
spriteBatch.Draw(this.player.Texture, this.player.Position, null, Color.White, this.player.Rotation, this.player.Origin, 1.0f, SpriteEffects.None, 0.0f);
spriteBatch.End();
base.Draw(gameTime);
Edit: forgot to mention, the velocity object used in the Move methods is a Vector2
I've managed to see it occur once for a split second which has led me to what I think is the problem. Since you are using the raw ElapsedGameTime.TotalMilliseconds value as a factor for your movement, all computer lag that your program experiences will be directly applied to the motion. For example, if your computer (OS) does something else for one twentieth of a second, then the elapsed time value will accumulate to a value of ~50 milliseconds, when it is normally about 0.3 milliseconds. This would cause a frame that has 150 times more motion than a normal frame.
To cause this to happen manually, you can do the following:
// define a frame counter
private int mCounter;
...
protected override void Update(GameTime pGameTime)
{
// save the elapsed time value
float time = (float)pGameTime.ElapsedGameTime.TotalMilliseconds;
...
// force a long frame every 2500th frame (change depending on your framerate)
if (mCounter++ > 2500)
{
mCounter = 0;
time = 75; // about 225 times longer frame
}
...
// use the time value in your move calls
if ((keyboard.IsKeyDown(Keys.Left)) || (gamePad.DPad.Left == ButtonState.Pressed))
mPlayer.MoveLeft(time);
To prevent this from happening, (aside from setting IsFixedTimeStep = true;, which would fix it immediately; but assuming you want IsFixedTimeStep to be false), you should use a time value, as above, but cap it. It's up to you to determine the proportion of elapsed time to motion and to determine what is a good amount of time to allow to pass per frame. Ex:
protected override void Update(GameTime pGameTime)
{
// save the elapsed time value
float time = (float)pGameTime.ElapsedGameTime.TotalMilliseconds;
if (time > 1)
time = 1;
...
if ((keyboard.IsKeyDown(Keys.Left)) || (gamePad.DPad.Left == ButtonState.Pressed))
mPlayer.MoveLeft(time);
...
While that will correct the issue for your current program, your frames are only at 0.3ms each since there is not a lot happening. Once there is more to your game, more time will be elapsing per frame, and you will want the cap to be much higher than 1ms.
EDIT: To be clear, this is 'downtime' from your CPU/OS. It's not going to go away*, it's just up to you whether to jump ahead a bunch when it happens (which can cause problems if the elapsed time ever makes it to 2000ms, for example), or to cap these spikes and let them cause lag; either way there is going to be a 'hole' in your motion that you can't fill. This really is normal, and it's not as critical as it seems. Once there is more happening in your game, it will become less and less noticeable. It stands out strongly at the moment particularly because there are only two graphics present and nothing else happening.
*(Actually, you might look for other applications and processes that you can close to keep the CPU from being borrowed by some other program, but since you are using a multi-tasking OS, you are never going to be guaranteed to have the CPU to yourself.)
Update Again
Just had a thought. Have you ever checked that (float)gameTime.ElapsedGameTime.TotalMilliseconds does not result in Infinity or a negative number? The elapsed time becoming negative would explain your sprite jumping back then forward.
Its the keyboard. You can prove this by changing moving left and right to left mouse and right mouse click. Use the keydown and keyup triggers to set a state instead of iskeydown.
Update:
It appears there are a few things that cause "stuttering" in XNA. I thought for sure your issue was the keyboard problem one. However, I can only assume you've tested your code with the GamePad also and it suffers the same.
There is another problem with IsFixedTimeStep but you already have that set to false. A quick google search suggests there are more than a few people with these types of problems without any clear fix.
There is a long discussion at http://forums.create.msdn.com/forums/t/9934.aspx?PageIndex=6
Other things to look at:
Try restricting your frame rate to 60 fps. There isn't any reason to go above that anyways. One power suggests that a 2d app that does nothing could stall the graphics pipeline with a significantly high throughput.
Check to see if IsSlowRunning is ever called. Garbage collection and Chaos Theory could cause this to be set. I